<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">## GetInfo.pm -- Database generator for Verilog design
## $Revision: #2 $$Date: 2005/10/10 $$Author: Rohit Mishra $
## Written by: Rohit Mishra &lt;rohit@rohitmishra.com&gt;
############################################################
package Verilog::GetInfo;

require 5.6.1;
use vars qw( $VERSION );
use strict;
use Carp;
use FileHandle;

$VERSION = '1.0.1';
##################################################################


##################################################################
# Package subroutines
##################################################################

##################################################################
sub new {
##################################################################
	@_ &gt;= 1 or croak 'usage: $verilog_handle = Verilog::GetInfo-&gt;new(\@command_line)';

	my $class = ref($_[0]) || $_[0];
        my $junk = shift(@_);
        my $command_line = shift(@_);
	my $self = {};
        my $command = undef;
        my $fh = undef; 
	
	# Database Hashes
	$self-&gt;{'DATABASE'} = { };
	$self-&gt;{'HIERARCHY'} = { };
	$self-&gt;{'Handle'} = undef;
	@{$self-&gt;{'NULL'}} = ('None');

	# Global Variables
	$self-&gt;{'GLOBAL'} = { };
	$self-&gt;{'GLOBAL'}-&gt;{'TRUE'} = 1;
	$self-&gt;{'GLOBAL'}-&gt;{'FALSE'} = 0;
	$self-&gt;{'GLOBAL'}-&gt;{'flag'} = 0;
	$self-&gt;{'GLOBAL'}-&gt;{'flag1'} = 0;
	$self-&gt;{'GLOBAL'}-&gt;{'level'} = 0;
	$self-&gt;{'GLOBAL'}-&gt;{'connec_flag'} = 0;
	@{$self-&gt;{'GLOBAL'}-&gt;{'indent'}} = ("\t");

 	# bless it as a Parser object
 	bless $self, $class;
        $command = $self-&gt;Parse_Command_Line( $command_line );
	if( ! defined $self-&gt;{'DATABASE'}-&gt;{'LOGFILE'} ){
               $self-&gt;{'DATABASE'}-&gt;{'LOGFILE'} = "verilog-shell_$VERSION\.log"; 
	}
        open( LOG, "&gt;$self-&gt;{'DATABASE'}-&gt;{'LOGFILE'}" ) || die("$!");
        $self-&gt;{Handle} = *LOG;
        select($self-&gt;{Handle});
        $| = 1;
        select(STDOUT);
        $| = 1;
	$self-&gt;Message($self-&gt;{Handle},"=" x 72);
	$self-&gt;Message($self-&gt;{Handle},"Command line: $command");
	$self-&gt;Message($self-&gt;{Handle},"=" x 72);
	$self-&gt;Read_Verilog_Files;
	return $self;
}

##################################################################
sub Parse_Command_Line(){
##################################################################
	@_ == 2
        or croak 'usage: $files = $verilog_handle-&gt;Parse_Command_Line( \@ARGV )';
        my $self = shift(@_);
	my $command_line = shift(@_);
	my $command = "$0\n";
	my $arguments;
	my $macro;
	my $value;
	my $line;
	my $directory;
	my $fh = FileHandle-&gt;new();


	while( $arguments = shift( @$command_line ) ){
		chomp( $arguments );
		$arguments =~ s/\s+//g;
		if( $arguments =~ m|\+define\+([A-Za-z0-9_]+)="(.*?)"| ){
			$macro = $1;
			$value = $2;
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = $value;
			$command .= " $arguments\n";
		} elsif( $arguments =~ m|\+define\+([A-Za-z0-9_]+)| ){
			$macro = $1;
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = "junk";
			$command .= " $arguments\n";
		} elsif( $arguments =~ m|\+incdir\+(.*)| ){
			$directory = $1;
			push( @{$self-&gt;{'DATABASE'}-&gt;{'INCDIR'}}, $directory );
			$command .= " $arguments\n";
		} elsif( $arguments =~ m|\+([A-Za-z0-9_]+)| ){
			$macro = $1;
			$self-&gt;{'DATABASE'}-&gt;{'PLUSARGS'}-&gt;{$macro} = "junk";
			$command .= " $arguments\n";
		} elsif( $arguments =~ m|\-f| ){
			$arguments = shift( @$command_line );
			push( @{$self-&gt;{'DATABASE'}-&gt;{'FILES'}}, $arguments );
			$command .= " -f $arguments\n";
		} elsif( $arguments =~ m|\-v| ){
			$arguments = shift( @$command_line );
			push( @{$self-&gt;{'DATABASE'}-&gt;{'LIBFILES'}}, $arguments );
			$command .= " -v $arguments\n";
		} elsif( $arguments =~ m|\-y| ){
			$arguments = shift( @$command_line );
                        push( @{$self-&gt;{'DATABASE'}-&gt;{'LIBDIRS'}}, $arguments );	
			$command .= " -y $arguments\n";
		} elsif( $arguments =~ m|\-l| ){
			$arguments = shift( @$command_line );
			$self-&gt;{'DATABASE'}-&gt;{'LOGFILE'} = $arguments;
			$command .= " -l $arguments\n";
		} else {
			push( @{$self-&gt;{'DATABASE'}-&gt;{'FILES'}}, $arguments );
			$command .= " $arguments\n";
			next;
		}
	}
        return $command;
}

##################################################################
sub Read_Verilog_Files(){
##################################################################
	@_ == 1 
	or croak 'usage: $verilog_handle-&gt;Read_Verilog_Files';
	my $self = shift(@_);
	my $file;
	my $top;
	
	my @files = @{$self-&gt;{'DATABASE'}-&gt;{'FILES'}};

	foreach $file ( @files ){
		my @data = $self-&gt;Verilog_To_Text( $file );
		$self-&gt;Read_Text( $file, @data );
	}
	
	$self-&gt;Generate_Module_Database;
	$top = $self-&gt;Get_Toplevel;
	foreach my $toplevel ( @$top ){
		$self-&gt;{'HIERARCHY'}-&gt;{$toplevel} = $self-&gt;Hierarchy( $toplevel );
	}
	$self-&gt;{'GLOBAL'}-&gt;{'flag'} = 0;
}
##################################################################
sub Verilog_To_Text(){
##################################################################
	@_ == 2 
	or croak 'usage: $verilog_handle-&gt;Verilog_To_Text( $filename )';
	my $self = shift( @_ );
	my $file = shift( @_ );
	my $line;
	my @data = ();

	my $fh = FileHandle-&gt;new();

	

	if( $fh-&gt;open( $file ) ){
		while( $line = $fh-&gt;getline() ){
			chomp($line);
			if( ( $line =~ m|^\s*//| ) || ( $line =~ m|^\s*$| ) ){
				next;
			} elsif( $line =~ m|(include\s+"\s*[A-Za-z0-9_/\.]+\s*")| ){
				push( @data, "`$1" );
			} elsif( $line =~ m|(.*?)//| ){ 
				push( @data, "$1" );
			} elsif( ( $line =~ m|^\s*/\*| ) &amp;&amp; ( $line =~ m|\*/\s*$| ) ){
				next;
			} elsif( ( $line =~ m|^\s*/\*| ) &amp;&amp; ( $line !~ m|\*/\s*$| ) ){
				while( $line = $fh-&gt;getline() ){
					if( $line =~ m|\*/\s*$| ){
						last;
					}
				}
			} elsif( $line =~ m|(.*?)/\*(.*?)\*/(.*?)| ){
				push( @data, "$1"."$3" );
			} else {
				push( @data, $line );
			}
		}
	} else {
		$self-&gt;Error( "Open failed: $file" );
                exit("1");
	}
	return( @data );
}


##################################################################
sub Read_Text(){
##################################################################
	@_ &gt;= 2
        or croak 'usage: $verilog_handle-&gt;Read_Text( $file,@data )';
        my $self = shift( @_ );
        my $file = shift( @_ );
        my @data = @_;
        my $line;
	my @data1 = ();
	my $level = 0;
	my $tag = 0;
	my $tag1 = 0;
	my %ifdef = ();
	my %else = ();
	my $i;
	my $line_number = 0;
	my $macro;
	my $value;
	my $module = undef;
	my @expand = ();

	if( $self-&gt;{'GLOBAL'}-&gt;{'level'} == 0 ){
		$self-&gt;Echo($self-&gt;{Handle}, "Reading file: $file" );
	} else {
		$self-&gt;Echo($self-&gt;{Handle}, "Reading level $self-&gt;{'GLOBAL'}-&gt;{'level'} include file: $file" );
	}

	while( $line = shift( @data )){
		$line_number++;

		# define ifdefs, elses and endif tags

		if( $line =~ m|\s*ifdef\s+(\S+)| ){
			$level++;
			if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$1} ){
				$ifdef{$level} = $self-&gt;{'GLOBAL'}-&gt;{'TRUE'};
				$else{$level} = $self-&gt;{'GLOBAL'}-&gt;{'FALSE'};
			} else {
				$ifdef{$level} = $self-&gt;{'GLOBAL'}-&gt;{'FALSE'};
				$else{$level} = $self-&gt;{'GLOBAL'}-&gt;{'FALSE'};
			}
			next;
		}
		if( $line =~ m|\s*else| ){
			$else{$level} = $self-&gt;{'GLOBAL'}-&gt;{'TRUE'};
			next;
		}
		if( $line =~ m|\s*endif| ){
			undef $ifdef{$level}; 	
			if( $else{$level} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} ){
				undef $else{$level};
			}
			$level--;
			next;
		}


		# ifdef conditions for which it should not move fwd

		if( defined $ifdef{$level} &amp;&amp; defined $else{$level} ){
			if( $ifdef{$level} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} &amp;&amp; $else{$level} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} ){
				next;
			} elsif( $ifdef{$level} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} &amp;&amp; $else{$level} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} ){
				next;
			} elsif( $ifdef{$level} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} &amp;&amp; $else{$level} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} ){

				# check for previous ifdefs
				foreach $i ( keys %ifdef ){
					if( defined $ifdef{$i} &amp;&amp; defined $else{$i} ){
						if( $i &lt; $level &amp;&amp; $ifdef{$i} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} &amp;&amp; $else{$i} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} ){
							$tag = 1;
							last;
						} elsif( $i &lt; $level &amp;&amp; $ifdef{$i} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'}  &amp;&amp; $else{$i} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} ){
							$tag = 1;
							last;
						}
					}
				}
				if( $tag == 1 ){
					$tag = 0;
					next;
				}
			} elsif( $ifdef{$level} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} &amp;&amp; $else{$level} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} ){

                                # check for previous ifdefs
                                foreach $i ( keys %ifdef ){
                                        if( defined $ifdef{$i} &amp;&amp; defined $else{$i} ){
                                                if( $i &lt; $level &amp;&amp; $ifdef{$i} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} &amp;&amp; $else{$i} == $self-&gt;{'GLOBAL'}-&gt;{'FALSE'} ){
                                                        $tag = 1;
                                                        last;
                                                } elsif( $i &lt; $level &amp;&amp; $ifdef{$i} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'}  &amp;&amp; $else{$i} == $self-&gt;{'GLOBAL'}-&gt;{'TRUE'} ){
                                                        $tag = 1;
                                                        last;
                                                }
                                        }
                                }
                                if( $tag == 1 ){
                                        $tag = 0;
                                        next;
                                }
			}
		}
		
		# plusargs conditions for which it should not move fwd.

		if( ($line =~ m|\$test\$plusargs\s*\(\s*\"\s*([A-Za-z0-9_]+)\s*"\s*\)|g) ){ # TEMP rohit&amp;&amp; ($line =~ m|\bbegin\b|g) ){
			$macro = $1;
			if( !defined $self-&gt;{'DATABASE'}-&gt;{'PLUSARGS'}-&gt;{$macro} ){
				$self-&gt;Warning( $self-&gt;{Handle},"Plusarg ($macro) not defined. Skipping.. ");
			        while( $line = shift( @data ) ){
                                        if( $line =~ m|\bend\b| ){
                                                last;
                                        } else {
                                                next;
                                        }
                                }
			} else {
				$self-&gt;Warning( $self-&gt;{Handle},"Plusarg ($macro) defined.");
			}
		} elsif( $line =~ m|\$test\$plusargs\s*\(\s*\"\s*([A-Za-z0-9_]+)\s*"\s*\)| ){
			$macro = $1;
			if( !defined $self-&gt;{'DATABASE'}-&gt;{'PLUSARGS'}-&gt;{$macro} ){
				$self-&gt;Warning( $self-&gt;{Handle},"Plusarg ($macro) not defined. Skipping.. ");
				$line = shift( @data );
				if( $line =~ m|\bbegin\b| ){
                                	while( $line = shift( @data ) ){
                                       		 if( $line =~ m|\bend\b| ){
                                       		         last;
                                       		 } else {
                                       		         next;
                                       		 }
                                	}
				} else {
					unshift( @data, $line );
					next;
				}
                        } else {
				$self-&gt;Warning( $self-&gt;{Handle},"Plusarg ($macro) defined.");
			}
		}


		if( $line =~ m|\s*define\s+([a-zA-Z0-9_]+)\s+"([\s\S]+)"| ){
			$macro = $1;
			$value = $2;
			@expand = ( $value =~ m|([A-Za-z0-9_]+)|g ); 
			while( @expand ){
				foreach ( @expand ){
					if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_} ){
						$value =~ s/\`$_/$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_}/g;
					} else {
						$value =~ s/\`$_//g;
					}
				}
				@expand = ( $value =~ m|([A-Za-z0-9_]+)|g );
			}
			$value =~ s/[\s\{\}\"]+//g;
			$value = join( "", split( /\,/, $value ) );

			if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} ){
				$self-&gt;Warning( $self-&gt;{Handle},"Text macro ($macro) re-defined. Replaced with new definition.\n$file: $line_number");
			}
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = $value;
		} elsif( $line =~ m|\s*`define\s+([a-zA-Z0-9_]+)\s+(\S+)| ){
			$macro = $1;
			$value = $2;
			@expand = ( $value =~ m|\`([A-Za-z0-9_]+)|g );
                        while( @expand ){
                                foreach ( @expand ){
                                        if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_} ){
                                                $value =~ s/\`$_/$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_}/g;
                                        } else {
						$value =~ s/\`$_//g;
					}
                                }
                                @expand = ( $value =~ m|\`([A-Za-z0-9_]+)|g );
                        }
                        $value =~ s/[\s\{\}\"]+//g;
                        $value = join( "", split( /\,/, $value ) );

			if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} ){
				$self-&gt;Warning( $self-&gt;{Handle},"Text macro ($macro) re-defined. Replaced with new definition.\n$file: $line_number");
			}
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = $value;
		} elsif( $line =~ m|\s*`define\s+([a-zA-Z0-9_]+)| ){
			$macro = $1;
			if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} ){
				$self-&gt;Warning( $self-&gt;{Handle},"Text macro ($macro) re-defined. Replaced with new definition.\n$file: $line_number");
			}
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = "junk";
		} elsif( $line =~ m|\s*`include(.*)|g ){
			$value = $1;
			@expand = ( $value =~ m|`([A-Za-z0-9_]+)|g );
			while( @expand ){
				foreach ( @expand ){
					if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_} ){
                                       	        $value =~ s/\`$_/$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_}/g;
                                       	} else {
                                       		$value =~ s/\`$_//g;
                                       	}		
				}
				@expand = ( $value =~ m|`([A-Za-z0-9_]+)|g );
			}
			$value =~ s/[\s\{\}\"]+//g;
                        $value = join( "", split( /\,/, $value ) );
			push( @data1, "`include \"$value\"" );
                } elsif( $line =~ m|`[A-Za-z0-9_]+|g ){
                        # Temporarily removed ` include expansions
                        #@expand = ( $line =~ m|`([A-Za-z0-9_]+)|g );
                        #while( @expand ){               
                        #        foreach ( @expand ){   
                        #                if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_} ){  
                        #                        $line =~ s/\`$_/$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$_}/g;
                        #                } else {
                        #                        $line =~ s/\`$_//g;
                        #                }              
                        #        }
                        #        @expand = ( $line =~ m|([A-Za-z0-9_]+)|g );
                        #}
                        #$line =~ s/[\s\{\}\"]+//g;
                        #$line = join( "", split( /\,/, $line ) );
                        #push( @data1, "\"$line\"" );
		} else {
			push( @data1, $line );
			next;
		}
	}
	$line_number = 0;

	while( $line = shift( @data1 )){
		if( $line =~ m|\s*include\s+"(\S+)"| ){
			my $incl_file = $1;
			$self-&gt;{'GLOBAL'}-&gt;{'level'}++;
			if( ! -f $incl_file ){ 
				foreach my $tmpvar ( @{$self-&gt;{'DATABASE'}-&gt;{'INCDIR'}} ){
					if( -f "$tmpvar/$incl_file" ){
						$incl_file = "$tmpvar/$incl_file";
						last;
					}
				}	
			}
       			push( @{$self-&gt;{'DATABASE'}-&gt;{'FILES'}},$incl_file);
			my @data1 = $self-&gt;Verilog_To_Text( $incl_file );
			$self-&gt;Read_Text( $incl_file, @data1 );
			$self-&gt;{'GLOBAL'}-&gt;{'level'}--;
		} elsif( $line =~ m|^\s*\-y\s+(\S+)| ){
			my $libdir = $1;
                        push( @{$self-&gt;{'DATABASE'}-&gt;{'LIBDIRS'}}, $libdir );	
			$self-&gt;Cache_Libdir( $libdir );
		} elsif( $line =~ m|^\s*\-v\s+(\S+)| ){
			my $libfile = $1;
                        push( @{$self-&gt;{'DATABASE'}-&gt;{'LIBFILES'}}, $libfile );	
			$self-&gt;Cache_Libfile( $libfile );
		} elsif( $line =~ m|\+define\+(\S+)| ){
			$macro = $1;
			$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$macro} = "junk";
		} elsif( $line =~ m|\+libext\+(\S+)| ){
			my $libext = $1;
			@{$self-&gt;{'DATABASE'}-&gt;{'LIBEXT'}} = split(/\+/, $libext );
		} elsif( $line =~ m|^\s*\+([A-Za-z0-9_]+)| ){
			$macro = $1;
			$self-&gt;{'DATABASE'}-&gt;{'PLUSARGS'}-&gt;{$macro} = "junk";
		} elsif( -f $line ){
       			push( @{$self-&gt;{'DATABASE'}-&gt;{'FILES'}},$line);
			my @data1 = $self-&gt;Verilog_To_Text( $line );
			$self-&gt;Read_Text( $line, @data1 );
		} else {
			push( @{$self-&gt;{'DATABASE'}-&gt;{'FULLVIEW'}}, $line );
			$self-&gt;{'DATABASE'}-&gt;{'FULL'}-&gt;{'CONTENTS'} .= "$line\n"; 
			next;
		}
	}
	return;
}

##################################################################
sub Cache_Libdir(){
##################################################################
	@_ == 2
        or croak 'usage: $verilog_handle-&gt;Cache_Libdir( $libdir )';
	my $self = shift(@_);
	my $libdir = shift(@_);
	my $line;
	my $libext;
	my $file;
	my @data = ();
	
	$self-&gt;Message($self-&gt;{Handle},"Scanning library directory: $libdir\n");
	opendir( DIR, $libdir ) || $self-&gt;Warning( $self-&gt;{Handle},"Could not open library directory:\n$libdir\n");
	while( $file = readdir( DIR ) ){
		foreach $libext ( @{$self-&gt;{'DATABASE'}-&gt;{'LIBEXT'}} ){
		        $libext =~ s/\s+//g;
			if( $file =~ m|$libext$| ){
				@data = $self-&gt;Verilog_To_Text( "$libdir/$file" );
				while( $line = shift( @data )){
					$self-&gt;{'DATABASE'}-&gt;{'LIBRARY'} .= "$line\n";
				}
			} else {
				next;
			}
		} 
	}
	closedir( DIR );
}

##################################################################
sub Cache_Libfile(){
##################################################################
        @_ == 2
        or croak 'usage: $verilog_handle-&gt;Cache_Libfile( $libfile )';
        my $self = shift(@_);
        my $libfile = shift(@_);
        my $line;
        my @data = $self-&gt;Verilog_To_Text( $libfile );
	$self-&gt;Message($self-&gt;{Handle},"Scanning library file: $libfile\n");
	while( $line = shift( @data )){
		$self-&gt;{'DATABASE'}-&gt;{'LIBRARY_FILE'} .= "$line\n";
	}	
}



##################################################################
sub Generate_Module_Database(){
##################################################################
	@_ == 1
        or croak 'usage: $verilog_handle-&gt;Generate_Module_Database';
        my $self = shift(@_);
        my @database = @{$self-&gt;{'DATABASE'}-&gt;{'FULLVIEW'}};
	my $line;
	my $module;
	my $i = 0;


	while( $line = shift( @database ) ){
		if ( $line =~ /\s*module\s+([A-Za-z0-9_]+)/ ){
			$module = $1;
			$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'} .= "$line\n";
			push( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'ARRAY'}}, $line );
			while( $line = shift( @database )){
				$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'} .= "$line\n";
				push( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'ARRAY'}}, $line );
				if( $line =~ /\s*endmodule/ ){
					last;
				} else {
					next;
				}
			}
			unshift( @database, $line );
			$i++;
		}
	}

	$self-&gt;{'DATABASE'}-&gt;{'MODCNT'} = $i;
}

##################################################################
sub Get_Inputs(){
##################################################################
        @_ == 2
        or croak 'usage: @inputs = $verilog_handle-&gt;Get_Inputs( $module )';
        my $self = shift(@_);
	my $module = shift(@_);
	my $line;
	my @inputs = ();

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
	my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};

	$data =~ s/\n//g;
	$data =~ s/\s+//g;
	if( $data =~ m|module$module;| ){
		return( @{$self-&gt;{'NULL'}} );
	}
	my @data = split(/;/,$data );

	while( $line = shift( @data )){
		if( $line =~ /^input(.*)/ ){
			$line = $1;
			if( $line =~ /\,/ ){
				push( @inputs, split(/,/,$line ));
			} else {
				push( @inputs, $line );
			}
		}
	}

	@{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'INPUTS'}} = @inputs;
	
	return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'INPUTS'}} );
}

##################################################################
sub Get_Outputs(){
##################################################################
        @_ == 2
        or croak 'usage: @outputs = $verilog_handle-&gt;Get_Outputs( $module )';
        my $self = shift(@_);
        my $module = shift(@_);
        my $line;
        my @outputs = ();

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
        my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};

        $data =~ s/\n//g;
        $data =~ s/\s+//g;
	if( $data =~ m|module$module;| ){
		return( @{$self-&gt;{'NULL'}} );
        }
        my @data = split(/;/,$data );

        while( $line = shift( @data )){
                if( $line =~ /^output(.*)/ ){
                        $line = $1;
                        if( $line =~ /\,/ ){
                                push( @outputs, split(/,/,$line ));
                        } else {
                                push( @outputs, $line );
                        }
                }
        }

        @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'OUTPUTS'}} = @outputs;

        return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'OUTPUTS'}} );
}


##################################################################
sub Get_Ports(){
##################################################################
        @_ == 2
        or croak 'usage: @ports = $verilog_handle-&gt;Get_Ports( $module )';
        my $self = shift(@_);
        my $module = shift(@_);
        my $line;
	my $portlist;

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
        my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};
	$data =~ s/\n//g;
	$data =~ s/\s+//g;
	if( $data =~ m|module$module;| ){
                return( @{$self-&gt;{'NULL'}} );
        }	
	if( $data =~ m|module$module\((.*?)\);| ){
		$portlist = $1;
	}
	my @ports = split(/,/, $portlist );
	@{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'PORTS'}} = @ports;

       	return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'PORTS'}} );
}


##################################################################
sub GetLoads(){
##################################################################
        @_ == 2
        or croak 'usage: @loads = $verilog_handle-&gt;GetLoads( $signal )'; 
        my $self = shift(@_);
        my $signal = shift(@_);
        my @loads = ();
        my $line = undef;

}

##################################################################
sub Get_Regs(){
##################################################################
        @_ == 2
        or croak 'usage: @regs = $verilog_handle-&gt;Get_Regs( $module )';
        my $self = shift(@_);
        my $module = shift(@_);
        my $line;
        my @regs = ();

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
        my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};
        $data =~ s/\n//g;
        $data =~ s/\s+//g;
        my @data = split(/;/,$data );

        while( $line = shift( @data )){
                if( $line =~ /^reg(.*)/ ){
                        $line = $1;
                        if( $line =~ /\,/ ){
                                push( @regs, split(/,/,$line ));
                        } else {
                                push( @regs, $line );
                        }
                }
        }

        @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'REGS'}} = @regs;

	if( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'REGS'}} ){
        	return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'REGS'}} );
	} else {
		return( @{$self-&gt;{'NULL'}} );
	}
}

##################################################################
sub Get_Wires(){
##################################################################
        @_ == 2
        or croak 'usage: @wires = $verilog_handle-&gt;Get_Wires( $module )';
        my $self = shift(@_);
        my $module = shift(@_);
        my $line;
        my @wires = ();

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
        my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};
        $data =~ s/\n//g;
        $data =~ s/\s+//g;
        my @data = split(/;/,$data );

        while( $line = shift( @data )){
                if( $line =~ /^wire(.*)/ ){
                        $line = $1;
                        if( $line =~ /\,/ ){
                                push( @wires, split(/,/,$line ));
                        } else {
                                push( @wires, $line );
                        }
                }
        }

        @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'WIRES'}} = @wires;

	if( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'WIRES'}} ){
        	return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'WIRES'}} );
	} else {
                return( @{$self-&gt;{'NULL'}} );
        }

}

##################################################################
sub Get_Inouts(){
##################################################################
        @_ == 2
        or croak 'usage: @inouts = $verilog_handle-&gt;Get_Inouts( $module )';
        my $self = shift(@_);
        my $module = shift(@_);
        my $line;
        my @inouts = ();

	if( !defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module} ){
		$self-&gt;Error("Module ($module) not present in the design.\n");
		return;
	}
        my $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'CONTENTS'};
        $data =~ s/\n//g;
        $data =~ s/\s+//g;
	if( $data =~ m|module$module;| ){
                return( @{$self-&gt;{'NULL'}} );
        }
        my @data = split(/;/,$data );

        while( $line = shift( @data )){
                if( $line =~ /^inout(.*)/ ){
                        $line = $1;
                        if( $line =~ /\,/ ){
                                push( @inouts, split(/,/,$line ));
                        } else {
                                push( @inouts, $line );
                        }
                }
        }

        @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'INOUTS'}} = @inouts;

        return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'INOUTS'}} );
}

##################################################################
sub Get_Toplevel(){
##################################################################
        @_ == 1
        or croak 'usage: $toplevel = $verilog_handle-&gt;Get_Toplevel';
        my $self = shift(@_);
        my $module;
        my @toplevel = ();
	my @top = ();
	my %found = ();

        my $data = $self-&gt;{'DATABASE'}-&gt;{'FULL'}-&gt;{'CONTENTS'};
	
	$data =~ s/\n+/ /g;

	%found = ( $data =~ m|[^\.]([A-Za-z0-9_]+)\s+([\#\(\)A-Za-z0-9_]+)\s*\(|g );

	foreach $module ( sort keys %{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}} ){
		if( !defined $found{$module} ){
			push( @toplevel, $module );
			push( @top, "$module\n" );
		}
	}

        $self-&gt;Message($self-&gt;{Handle}, "Highest level modules:\n @top" );

        $self-&gt;{'DATABASE'}-&gt;{'TOPLEVEL'} = \@toplevel;

        return( $self-&gt;{'DATABASE'}-&gt;{'TOPLEVEL'} );
}



##################################################################
sub Hierarchy(){
##################################################################
        @_ == 2
        or croak 'usage: $verilog_handle-&gt;Hierarchy( $top )';
        my $self = shift(@_);
        my $toplevel = shift(@_);
        my $module;
        my $data;
        my $hierarchy = { };
        my @found = ();
	my @mod_inst = ();

	if( ! defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$toplevel} ){
		$self-&gt;Error("Module ($toplevel) is not present in the design.\n");
		return undef;
	}
	
	if( $self-&gt;{'GLOBAL'}-&gt;{'flag'} == 0 ){
		$self-&gt;Message($self-&gt;{Handle},"\tBuilding module hierarchy hashes ..\n");
		$self-&gt;{'GLOBAL'}-&gt;{'flag'} = 1;
	}

        $data = $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$toplevel}-&gt;{'CONTENTS'};
	$data =~ s/\n+/ /g;
	@found = ( $data =~ m|([A-Za-z0-9_]+\s+[A-Za-z0-9_]+)\s*\(\s*[\.\\A-Za-z0-9_\[\]]+\s*\(|g );
	foreach $module ( @found ){
		@mod_inst = split( /\s+/, $module );
		$mod_inst[0] =~ s/\s+//g;
		$mod_inst[1] =~ s/\s+//g;
		if( defined $self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$mod_inst[0]} ){
			$self-&gt;{'DATABASE'}-&gt;{'INSTANCES'}-&gt;{$mod_inst[1]} = $mod_inst[0];
			$hierarchy-&gt;{$mod_inst[1]} = $self-&gt;Hierarchy( $mod_inst[0] );
		} else {
			push( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{'NODEFINITION'}}, $mod_inst[0] );
			next;
		}
	}
        return( $hierarchy );
}

##################################################################
sub Print_Hierarchy(){
##################################################################
        @_ == 2
        or croak 'usage: $verilog_handle-&gt;Print_Hierarchy( $hierarchy )';
	my $self = shift(@_);
	my $hierarchy = shift(@_);
	my $module;
	
	if( ! defined $hierarchy ){
		$self-&gt;Error("No hierarchy to display.\n");
		return undef;
	}
	foreach $module ( keys %{$hierarchy} ){
		$self-&gt;Message($self-&gt;{Handle},"@{$self-&gt;{'GLOBAL'}-&gt;{'indent'}} $module\n");
		push( @{$self-&gt;{'GLOBAL'}-&gt;{'indent'}},"\t");
		$self-&gt;Print_Hierarchy( $hierarchy-&gt;{$module} );
		pop( @{$self-&gt;{'GLOBAL'}-&gt;{'indent'}});
	}
	return;
}


##################################################################
sub Get_Define(){
##################################################################
        @_ &gt;= 1
        or croak 'usage: $verilog_handle-&gt;Get_Define or $verilog_handle-&gt;Get_Define( $define )';
        my $self = shift(@_);
	my $define;
	if( @_ ){
		$define = shift(@_);
		if( defined $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$define} ){
			if( $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$define} eq "junk" ){
				$self-&gt;Message($self-&gt;{Handle},"Text Macro $define set.");
				return;
			} else {
				$self-&gt;Message($self-&gt;{Handle},"Text Macro $define set to $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$define}\n");
				return;
			}
		} else {
			$self-&gt;Message($self-&gt;{Handle},"Text Macro $define not defined.\n");
			return;
		}
	} else {
		foreach $define ( sort keys %{$self-&gt;{'DATABASE'}-&gt;{'DEFINES'}} ){
			if( $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$define} eq "junk" ){
				$self-&gt;Message($self-&gt;{Handle},"Text macro $define set.\n");
			} else {
				$self-&gt;Message($self-&gt;{Handle},"Text macro $define set to $self-&gt;{'DATABASE'}-&gt;{'DEFINES'}-&gt;{$define}\n");
			}
		}
		return;
	}
	return;
}

##################################################################
sub Get_Files{
##################################################################
	@_ == 1 
	or croak 'usage: @verilog_files = $verilog_handle-&gt;Get_Files';
	if( @_ ){
		return ( @{$_[0]-&gt;{'DATABASE'}-&gt;{'FILES'}} );
	} else {
		return undef;
	}
}

##################################################################
sub Get_Module_Count{
##################################################################
        @_ == 1
        or croak 'usage: $no_of_modules = $verilog_handle-&gt;Get_Module_Count';

        if( @_ ){
                return ( $_[0]-&gt;{'DATABASE'}-&gt;{'MODCNT'});
        } else {
                return undef;
        }
}

##################################################################
sub Get_Modules{
##################################################################
	@_ == 1
	or croak 'usage: @modules = $verilog_handle-&gt;Get_Modules';
	my $self = $_[0];
	my @modules = ();

	if( @_ ){
		foreach ( keys ( %{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}} ) ){
			push( @modules,$_);
		}
		return( @modules );
	} else {
		return undef;
	}
}

##################################################################
sub Get_Full_Design{
##################################################################
        @_ == 1
        or croak 'usage: @design = $verilog_handle-&gt;Get_Full_Design';
        if( @_ ){
                return( @{$_[0]-&gt;{'DATABASE'}-&gt;{'FULLVIEW'}} );
        } else {
                return undef;
        }
}

##################################################################
sub Get_Module_Contents(){
##################################################################
        @_ == 2
        or croak 'usage: $module_content = $verilog_handle-&gt;Get_Module_Contents( $module )';

	my $self = shift(@_);
	my $module = shift(@_);

        if( defined $module ){
                return( @{$self-&gt;{'DATABASE'}-&gt;{'MODULES'}-&gt;{$module}-&gt;{'ARRAY'}} );
        } else {
                return undef;
        }
}


##################################################################
sub Message(){
##################################################################
        @_ &lt;= 3
        or croak 'usage: $verilog_handle-&gt;Message( &lt;message&gt; ); or $verilog_handle-&gt;Message( &lt;file handle&gt;, &lt;message&gt; );';
	my $self = shift;
        my $fh = undef;
        my $msg = undef;
        if( @_ == 2 ){
                $fh = shift;
	        $msg = shift;
        } else {
	        $msg = shift;
        }
        $msg =~ s/(.{72,72})/$1\n/g; 
        if( defined $fh ){
                print $fh "$msg\n";
                print "$msg\n";
        } else {
                print "$msg\n";
        }
}

##################################################################
sub Warning(){
##################################################################
        @_ &lt;= 3
        or croak 'usage: $verilog_handle-&gt;Warning( &lt;message&gt; ); or $verilog_handle-&gt;Warning( &lt;file handle&gt;, &lt;message&gt; );';
	my $self = shift;
        my $fh = undef;
        my $msg = undef;
        if( @_ == 2 ){
                $fh = shift;
	        $msg = shift;
        } else {
	        $msg = shift;
        }
        $msg =~ s|\n+|\n         |g;
        $msg =~ s/(.{72,72})/$1\n         /g; 
        if( defined $fh ){
                print $fh "Warning! $msg\n";
                print "Warning! $msg\n";
        } else {
                print "Warning! $msg\n";
        }
 
}

##################################################################
sub Echo(){
##################################################################
        @_ &lt;= 3
        or croak 'usage: $verilog_handle-&gt;Echo( &lt;message&gt; ); or $verilog_handle-&gt;Echo( &lt;file handle&gt;, &lt;message&gt; );';
	my $self = shift;
        my $fh = undef;
        my $msg = undef;
        if( @_ == 2 ){
                $fh = shift;
	        $msg = shift;
        } else {
	        $msg = shift;
        }
        if( defined $fh ){
                print $fh $msg,"\n";
                print $msg,"\n";
        } else {
                print $msg,"\n";
        }  
}

##################################################################
sub Error(){
##################################################################
        @_ &lt;= 3
        or croak 'usage: $verilog_handle-&gt;Error( &lt;message&gt; ); or $verilog_handle-&gt;Error( &lt;file handle&gt;, &lt;message&gt; );';
	my $self = shift;
        my $fh = undef;
        my $msg = undef;
        if( @_ == 2 ){
                $fh = shift;
	        $msg = shift;
        } else {
	        $msg = shift;
        }
        $msg =~ s/(.{72,72})/$1\nError! /g; 
        if( defined $fh ){
                print $fh "-" x 80,"\n";
                print $fh "Error! $msg\n";
                print $fh "-" x 80,"\n";
        } else {
                print "-" x 80,"\n";
                print "Error! $msg\n";
                print "-" x 80,"\n";
        }
}

1;

__END__

=head1 NAME

GetInfo.pm - Get information on a verilog HDL design

=head1 SYNOPSIS

Verilog::GetInfo.pm   version 1.0.1

=head1 STATUS

GetInfo.pm is in its beta version. Report all bugs to the author.

=head1 DESCRIPTION

Verilog::Getinfo.pm is a complete verilog HDL language parser. 

          $handle = Verilog::GetInfo-&gt;new(\@command_line)';

Above command will return a handle to the new verilog design database.
@command_line is the verilog command line options understood by GetInfo.
Most of the standard (IEEE 1364) command line options are supported.

Some of the options which are supported are:
-v, -y, + ( plusargs ), +define+, -l etc.

GetInfo understands most of the in-the-file options of Verilog HDL language:
`ifdef...`else...`endif
`include "filename.v"
`define macro value
`define macro

Some of the functions which return information about the design are:

=item Get_Inputs( module_name ) - Returns list of input ports of the module.
      It will return an array, with all the inputs along with their bus 
      widths.

=item Get_Outputs( module_name ) - Returns list of output ports of the module.
      An array with all the output ports listed along with their bus
      widths.

=item Get_Ports( module_name ) - Returns list of ports of a module.

=item Get_Regs( module_name ) - Returns list of registers defined in a module.

=item Get_Wires( module_name) - Returns list of wires defined in a module.

=item Get_Inouts( module_name) - Returns list of inout ports in a module.

=item Get_Toplevel() - Returns list of module names, which are not instantiated
      inside any other modules. 

=item Hierarchy( module_name ) - The module_name can be any module in the design.
      Returns a reference to a hash containing the hierarchy information of the
      module. It will report all the sub-modules below the module provided as the
      input to the function.

=item Print_Hierarchy( module_name ) - This function calls the function Hierarchy(),
      and prints the hierarchy in the nice human readable form.

=item Get_Define() - If an input is given to this function it will check, whether
      it is defined. If it is defined, it will check whether its a macro definition
      and return the value of the macro. 
      If no input is given, it will return all the defines that have been defined
      in the design, with their values.


=item Get_Files() - This function returns all the design files read into the
      database.

=item Get_Module_Count() - This function returns the total number of modules
      in the design.

=item Get_Modules() - This functions lists all the modules in the design.

=item Get_Full_Design() - This function returns a full flat netlist in an 
      array. Note: The array will be huge.

=item Get_Module_Contents() - This function returns the contents ( without comments )
      of a module provided as an input to this function.

=item Message(), Warning(), Echo(), Error() - Display functions. Will display lot 
      of information when parsing the design files.


=head1 BUGS
No known bugs. Plz report all the bugs to the author ( see AUTHOR section below )


=head1 AUTHOR

Rohit Mishra E&lt;lt&gt;F&lt;rohit@rohitmishra.com&gt;E&lt;gt&gt;

=head1 COPYRIGHT

Copyright (c) 2005 Rohit Mishra &lt;rohit@rohitmishra.com&gt;. All rights reserved
This program is a free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut
</pre></body></html>