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