jimjim2k
Advanced Member level 3
perl for eda
Hi to all
AS I had promised in:
1. h**p://
I start to collect useful perl scripts on EDA here:
Please help to gain this topic
-------------------------------------------------------------------------------------
1. Spectre to hspice converion tool:
-------------------------------------------------------------------------------------
Hi to all
AS I had promised in:
1. h**p://
I start to collect useful perl scripts on EDA here:
Please help to gain this topic
-------------------------------------------------------------------------------------
1. Spectre to hspice converion tool:
Code:
#!/usr/bin/perl
# Nelson Hu
# EE464H
# 08/07/03
#######################################################
# This program "Spectre2Hspice.pl" generates Hspice code from
# Spectre netlist (si.inp)
# The ouput of this program will then be able to run in Hspice
# for timing analysis
#######################################################
# how to use this program:
# in the folder where si.inp is found, type
# perl /home/projects/abraham/vlsi464/spicetest/FinalTOOLS/Spectre2Hspice.pl si.inp 3
# the number 3 at the end is the resolution for the timing analysis. it there is a longer delay, a larger number is used
# so that when running Hspice, the code will not fail.
#######################################################
# Input:
# si.inp
# a number for resolution.
#######################################################
# Output:
# %CELLNAME%.sp
#######################################################
# Transition Time and Output Capacitance
# Hspice will use these two column to generate a matrix of timing analysis
#######################################################
#transition time
@a = qw *5ps 50ps 100ps 150ps 200ps 250ps 300ps*;
#capacitance
@b = qw *0ff 3.5ff 17.5ff 35ff 87.5ff 105ff 231ff*;
#before 07/19/03
#@a = qw *0 10.695ps 40.71ps 70.75ps 156.49ps 301.6ps 591.8ps*;
#@b = qw *0 2FF 8FF 20FF 50FF 100FF 200FF* ;
#seokjin suggested
#@a = qw *0.03ps 0.1ps 0.4ps 0.9ps 1.5ps 2.2ps 3ps*;
#@b = qw *0.00035pf 0.021pf 0.0385pf 0.084pf 0.147pf 0.231pf 0.3115pf*;
#######################################################
# get the file name (usually si.inp)
#######################################################
open LALA, "$ARGV[0]";
@line = <LALA>;
close LALA;
#######################################################
# get the second argument, the resolution
#######################################################
$hp = $ARGV[1];
#######################################################
# aquire the name of the cell from si.inp and use the
# name of the cell to create %CELLNAME%.sp
#######################################################
foreach (@line){
if ($_ =~ /Design cell name:/){
@temp = split / /,$_;
$filename = $temp[$#temp];
chomp $filename;}}
open HSPICE, ">$filename.sp";
#######################################################
# look for gate and number of input
# $OtherInput is either "gnd" or "vdd".
# it specifies for multiple inputs to tie all to gnd or vdd
# $Inverted is either "T" or "F".
# it tells the program that the gate is inverted
# this section needs to be added for new type of logic cells
#######################################################
$NumberOfInput = $filename;
if ($filename =~ /inv/){
$NumberOfInput = 1;
$output = "Z";
$inverted = "T";}
elsif ($filename =~ /buf/){
$NumberOfInput = 1;
$output = "Z";
$inverted = "F";}
elsif ($filename =~ /mux/){ #might not work
$NumberOfInput = 3;
$OtherInput = " vdd";
$output = "Z";
$inverted = "F";}
elsif ($filename =~ /nand/){
$NumberOfInput =~ s/nand//g;
$NumberOfInput =~ s/x[\d]+//g;
$OtherInput = " vdd";
$output = "Z";
$inverted = "T";}
elsif ($filename =~ /nor/){
$NumberOfInput =~ s/nor//g;
$NumberOfInput =~ s/x[\d]+//g;
$OtherInput = " gnd";
$output = "Z";
$inverted = "T";}
elsif ($filename =~ /xor/){
$NumberOfInput =~ s/xor//g;
$NumberOfInput =~ s/x[\d]+//g;
$OtherInput = " gnd";
$output = "Z";
$inverted = "F";}
elsif ($filename =~ /and/){
$NumberOfInput =~ s/and//g;
$NumberOfInput =~ s/x[\d]+//g;
$OtherInput = " vdd";
$output = "Z";
$inverted = "F";}
elsif ($filename =~ /or/){
$NumberOfInput =~ s/or//g;
$NumberOfInput =~ s/x[\d]+//g;
$OtherInput = " gnd";
$output = "Z";
$inverted = "F";}
if ($NumberOfInput == 1){
$input = "A";}
if ($NumberOfInput == 2){
$input = "A B";}
if ($NumberOfInput == 3){
$input = "A B C";}
if ($NumberOfInput == 4){
$input = "A B C D";}
if ($NumberOfInput == 5){
$input = "A B C D E";}
$inout = $input." ".$output;
#######################################################
# to replace the "\" and carriage return (if the line is too long)
# with carriage return and a "+" in HSPICE format
#######################################################
for ($n = 0; $n <= $#line; $n++){
if ($line[$n] =~ /\\\n/){
chomp $line[$n];
chop $line[$n];
$line[$n] .= $line[($n + 1)];
$line[$n] =~ s/ //g;}
}
#######################################################
# to discard all the lines except the one starts with
# _inst
#######################################################
$n = 0;
foreach (@line) {
if ($_ =~ /_inst\d+/){
$new[$n] = $_;
$n++;}
}
#######################################################
# replace _inst with C* or M* and take out the word
# capacitor and region=sat. also take out "(", ")", "!"
#######################################################
$M = 1; $C = 1;
foreach (@new) {
if (($_ =~ /tsmc20P/) or ($_ =~ /tsmc20N/)){
$_ =~ s/_inst[\d]+/M$M/g;
$M++;}
if ($_ =~ /capacitor/){
$_ =~ s/_inst[\d]+/C$C/g;
$C++;
$_ =~ s/capacitor//g;}
$_ =~ s/ region\=sat//g;
$_ =~ s/\(//g;
$_ =~ s/\)//g;
$_ =~ s/\!//g;
$_ =~ s/ / /g;}
#######################################################
# duplicate m if m is greater than 2
#######################################################
foreach (@new) {
@values = split / /,$_;
$values[$#values] =~ s/m=//g;
$temp = $values[$#values];
chomp $temp;
$values[$#values] = "\n";
$_ = join " ",@values;
$temp--;
$copy = $_;
for (1..$temp) {
$new[$#new + 1] = $copy;
@change = split / /,$new[$#new];
if ($change[0] =~ s/M[\d]+/M$M/g){;
$M++;}
if ($change[0] =~ s/C[\d]+/C$C/g){;
$C++;}
$new[$#new] = join " ",@change;
}}
#######################################################
# exchange w,l; as,ad; ps,pd
#######################################################
foreach (@new) {
@values = split / /,$_;
if ($values[0] =~ /M(\d)/){
($values[7], $values[6]) = ($values[6], $values[7]);
($values[9], $values[8]) = ($values[8], $values[9]);
($values[11], $values[10]) = ($values[10], $values[11]);}
$_ = join " ",@values;}
#######################################################
# adding the beginning of the file
#######################################################
$middle = join " ",@new;
$middle =~ s/\n /\n/g;
$top_middle = "\*".$filename.".sp\n.options SPICE NOMOD AUTOSTOP LVLTIM=3\n.param ttra=0.1n LV=0.1e-12\n.temp 27\n\n.include \"/usr/local/packages/cadence/local/models/hspice/standalone/tsmc20P.m\"\n.include \"/usr/local/packages/cadence/local/models/hspice/standalone/tsmc20N.m\"\n.global vdd\n.global gnd\n\n\n.subckt $filename $inout\n". $middle.".ends\n";
#######################################################
# find number of input
#######################################################
@input = split / /,$input;
$n_input = $#input; #number of input - 1
$G = " gnd";
$V = " vdd";
$I = " input";
$O = " output";
chomp $hp;
$period = $hp + $hp;
$wholeperiod = $period + $hp;
$resolution = (($period + 1) / 10000);
print "the resolution is ".$resolution."\n";
$lastpart = "X".$filename.$I.$OtherInput x $n_input.$O." ".$filename."\nCLOAD".$O.$G." LV\n\nVa".$I.$G." PULSE\(0,3.3,1p,Ttra,Ttra,".$hp."n,".$period."n\)\n\nvdd".$V.$G." 3.3\n\n";
#######################################################
# middie-last part
#######################################################
if ($inverted eq "T"){
$abc = ".MEAS TRAN cell_rise TRIG V($I) val=1.65 TD=0n fall=1\n+\tTARG V($O) val=1.65 rise=1\n".
".MEAS TRAN cell_fall TRIG V($I) val=1.65 TD=0n rise=1\n+\tTARG V($O) val=1.65 fall=1\n".
".MEAS TRAN rise_slew TRIG V($O) val=0.33 TD=0n rise=1\n+\tTARG V($O) val=2.97 rise=1\n".
".MEAS TRAN fall_slew TRIG V($O) val=2.97 TD=0n fall=1\n+\tTARG V($O) val=0.33 fall=1\n".
".TRAN ".$resolution."N ".$wholeperiod."N sweep DATA=DATNM\n";}
elsif ($inverted eq "F"){
$abc = ".MEAS TRAN cell_rise TRIG V($I) val=1.65 TD=0n rise=1\n+\tTARG V($O) val=1.65 rise=1\n".
".MEAS TRAN cell_fall TRIG V($I) val=1.65 TD=0n fall=1\n+\tTARG V($O) val=1.65 fall=1\n".
".MEAS TRAN rise_slew TRIG V($O) val=0.33 TD=0n rise=1\n+\tTARG V($O) val=2.97 rise=1\n".
".MEAS TRAN fall_slew TRIG V($O) val=2.97 TD=0n fall=1\n+\tTARG V($O) val=0.33 fall=1\n".
".TRAN ".$resolution."N ".$wholeperiod."N sweep DATA=DATNM\n";}
#######################################################
# vary capacitance and delay time
# change @a, @b on top
#######################################################
@c;
$#c = 0;
foreach $a (@a) {
foreach $b (@b) {
$c[$#c++] = ($a."\t".$b."\n");}}
$c = join " ",@c;
$c =~ s/\n /\n/g;
$datnm = ".DATA DATNM\nTtra\tLV\n$c.ENDDATA\n";
#print $datnm;
#######################################################
# change .alter
#######################################################
@last;
$count = 2;
for (1..$n_input){
$last[0] = "X$filename";
$last[1] = $OtherInput;
for (1..$n_input){
$last[$_ + 1] = $OtherInput;}
$last[$count++] = $I;
$last .= ".alter\n@last $O $filename\n";
}
$last .= ".end\n";
#######################################################
# combine all
#######################################################
$final = "$top_middle"."\n"."$lastpart"."$abc\n"."$datnm"."\n"."$last";
print HSPICE $final;
close HSPICE;
-------------------------------------------------------------------------------------