Creating .lib file from verilog

Last modified 2012-12-13

Sini

Creating a dummy .lib file is something every physical design engineer has done now and then. If you have a verilog model of the block available, your task gets easier. The following script automates .lib generation from your verilog netlist. Use this as a dummy .lib to get your design flow going or use it as a template for your analog blocks for modifying the values.

Customize, edit and use. The script creates a simple Data Structre. So any modification can be done pretty easily. The script parses the verilog for the module name specified, and collects the ports & directions. In the .lib file written out, a default capacitance and transition value is specified. This is a good starting point for your blocks.

`Usage: createlib [transitionvalue] [capacitancevalue]`


use strict;

if ($#ARGV < 1 ) {
	print "usage: createlib \\n";
	exit;
}

my $netlist = $ARGV\[0\] ;
my $module  = $ARGV\[1\] ;
my $tran = 2.5 ;
my $cap = 0.001;
my $signallevel = "VDD" ;

if(defined $ARGV\[2\]) {$tran = $ARGV\[2\];}
if(defined $ARGV\[3\]) {$cap = $ARGV\[3\];}
if(defined $ARGV\[4\]) {$signallevel = $ARGV\[4\];}

my $FF;
my $FO;
open $FF, "< $ARGV\[0\]" or die "Can't open $ARGV\[0\] : $!";
open $FO, ">$module.lib" or die "Can't open $module.lib for write : $!";

my $db = createTopLevelDB(); 
createDotLib($db,$FO);

sub createDotLib
{
	my $topLevelDBRef = shift;
	my $FO = shift ;	
	### Header 
	print $FO "library\\($topLevelDBRef->{'design'}->{'cell'}\\) {\\n";
	print $FO "\\n /\* unit attributes \*/\\n";
	print $FO "  timeunit : \\"1ns\\"\\;\\n";
	print $FO "  voltageunit : \\"1V\\"\\;\\n";
	print $FO "  currentunit : \\"1uA\\"\\;\\n";
	print $FO "  pullingresistanceunit : \\"1kohm\\"\\;\\n";
	print $FO "  leakagepowerunit : \\"1nW\\"\\;\\n";
	print $FO "  capacitiveloadunit\\(1,pf\\)\\;\\n\\n";
	foreach my $direction (keys(%{$topLevelDBRef->{'bus'}})) {
		foreach my $bustype (keys %{$topLevelDBRef->{'bus'}->{$direction}}) {
			my @buswidth =  split(//, $bustype); 
			my $bushi = $buswidth\[1\] ;
			my $buslo = $buswidth\[2\] ;
			my $buswidth = $bushi+1-$buslo;
			print $FO " type \\($bustype\\) { \\n";
			print $FO "   basetype : array ; \\n" ;
    			print $FO "   datatype : bit  \\n" ;;
    			print $FO "   bitwidth : $buswidth   \\n" ;;
    			print $FO "   bitfrom : $bushi  \\n" ;;
    			print $FO "   bitto : $buslo ; \\n" ;
    			print $FO "   downto : true ; \\n" ;
    			print $FO " } \\n" ;
		}
	}
	print $FO "\\n  cell\\($topLevelDBRef->{'design'}->{'cell'}\\) {\\n";
	foreach my $direction (keys(%{$topLevelDBRef->{'pins'}})) {
		foreach my $pinname (@{$topLevelDBRef->{'pins'}->{$direction}}) {
			print $FO ("    pin\\($pinname\\) { \\n");
			print $FO ("\\tdirection : $direction ;\\n");
			if($direction eq "input") {
				print $FO ("\\tmaxtransition : $tran;\\n");
			}
			print $FO ("\\tcapacitance : $cap; \\n");  	
			print $FO ("    } \\n") ;
		}
	}
	foreach my $direction (keys(%{$topLevelDBRef->{'bus'}})) {
		foreach my $bustype (keys %{$topLevelDBRef->{'bus'}->{$direction}}) {
			my @buswidth =  split(//, $bustype); 
			my $bushi = $buswidth\[1\] ;
			my $buslo = $buswidth\[2\] ;
			foreach my $busname (@{$topLevelDBRef->{'bus'}->{$direction}{$bustype}}) {
                                        chomp($busname);
				print "BUS $busname : $bustype : $direction \\n" ;
				print $FO ("    bus\\($busname\\) { \\n");
				print $FO ("\\tbustype : $bustype ;\\n");
				print $FO ("\\tdirection : $direction ;\\n");
				if($direction eq "input") {
					print $FO ("\\tmaxtransition : $tran;\\n");
				}	
				for(my $i=$buslo; $i<=$bushi; $i++) {
					print $FO ("\\tpin\\($busname\\\[$i\\\]\\) { \\n");
					print $FO ("\\t\\tcapacitance : $cap; \\n");  
					print $FO ("\\t} \\n") ;
				}
				print $FO ("    } \\n") ;
			}
		}
	}
	print $FO ("  } \\n") ;
	print $FO ("} \\n") ;
}

sub createTopLevelDB 
{
	my $findtopmodule = 0; 
	my %topLevelDB = () ;
	my %pins = () ;
	my %bus = () ;
	my @inputpins ;
	my @outputpins ;
	my @inoutpins ;
	my @bustypes ; 
	my %inputbus = () ;
	my %outputbus = () ;
	my %inoutbus = () ;
	my %design = ();
	$design{'cell'} = $module; 
	$design{'tran'} = $tran; 
	$design{'cap'} = $cap; 
	$design{'signallevel'} = $signallevel; 
	while(my $line = <$FF>) {
		last if($findtopmodule == 1);
		if($line=~/module\\s+$module/) {
			$findtopmodule = 1 ;
			while(my $line = <$FF>) {
				next if($line =~ "\\s\*//" );
				chomp($line);
				if ($line =~/input\\s+/ ) {
					$line=~s/\\s\*input\\s+//;
					$line=~s/;//;
					if($line =~/\\\[(\\d+):(\\d+)\\\]/) { 
						my $bustype = "bus$1$2";
						$line=~s/\\\[(\\d+):(\\d+)\\\]//;
						my @line =  split(/,/, $line); 
						unless(grep {$ eq $bustype} @bustypes) {  
							push(@bustypes,$bustype);
						}
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@{$inputbus{$bustype}}, $pin );
						}
					}
					else {
						my @line =  split(/,/, $line); 
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@inputpins, $pin); 
						}
					}
				}
				if ($line =~/output\\s+/ ) {
					$line=~s/\\s\*output\\s+//;
					$line=~s/;//;
					if($line =~/\\\[(\\d+):(\\d+)\\\]/) { 
						my $bustype = "bus$1$2";
						$line=~s/\\\[(\\d+):(\\d+)\\\]//;
						my @line =  split(/,/, $line); 
						unless(grep {$ eq $bustype} @bustypes) {  
							push(@bustypes,$bustype);
						}
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@{$outputbus{$bustype}}, $pin );
						}
					}
					else {
						my @line =  split(/,/, $line); 
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@outputpins, $pin); 
						}
					}

				}
				if ($line =~/inout\\s+/ ) {
					$line=~s/\\s\*inout\\s+//;
					$line=~s/;//;
					if($line =~/\\\[(\\d+):(\\d+)\\\]/) { 
						my $bustype = "bus$1$2";
						$line=~s/\\\[(\\d+):(\\d+)\\\]//;
						my @line =  split(/,/, $line); 
						unless(grep {$ eq $bustype} @bustypes) {  
							push(@bustypes,$bustype);
						}
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@{$inoutbus{$bustype}}, $pin );
						}
					}
					else {
						my @line =  split(/,/, $line); 
						foreach my $pin (@line) {
							$pin=~s/\\s+//;
							push(@inoutpins, $pin); 
						}
					}

				}

				last if($line=~/endmodule/);
			}

		}
	}
	$pins{'input'} = \\@inputpins;
	$pins{'output'} = \\@outputpins;
	$pins{'inout'} = \\@inoutpins;
	$bus{'input'} = \\%inputbus;
	$bus{'output'} = \\%outputbus;
	$bus{'inout'} = \\%inoutbus;
	$topLevelDB{'pins'} = \\%pins;
	$topLevelDB{'bus'} = \\%bus;
	$topLevelDB{'design'} = \\%design;
	return \\%topLevelDB;
}```