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; }```