#!/usr/bin/perl
# Nelson Hu
# EE464H
# 8/4/03

#######################################################
# This program "CapaFinder.pl" will generate Hspice file to
# calculate input capacitance from a cell

#######################################################
# how to use this program:
# at the folder where si.inp located, type
#    perl /home/projects/abraham/vlsi464/spicetest/FinalTOOLS/CapaFinder.pl

#######################################################
# Input:
#  si.inp

#######################################################
# Output:
#  %CELLNAME%cap.sp

###############################################
# get the file name
###############################################
@line = <>;
foreach (@line){
	if ($_ =~ /Design cell name:/){
		@temp = split / /,$_;
		$filename = $temp[$#temp];
		chomp $filename;}}

open HSPICE, ">$filename"."cap.sp";

############################################
# look for gate and number of input
############################################

$NumberOfInput = $filename;
if ($filename =~ /inv/){
    $NumberOfInput = 1;
    $output = "Z";}
elsif ($filename =~ /buf/){
    $NumberOfInput = 1;
    $output = "Z";}
elsif ($filename =~ /mux/){   #might not work
    $NumberOfInput = 3;
    $OtherInput = " vdd";
    $output = "Z";}
elsif ($filename =~ /nand/){
    $NumberOfInput =~ s/nand//g;
    $NumberOfInput =~ s/x[\d]+//g;
    $OtherInput = " vdd";
    $output = "Z";}
elsif ($filename =~ /nor/){
    $NumberOfInput =~ s/nor//g;
    $NumberOfInput =~ s/x[\d]+//g;
    $OtherInput = " gnd";
    $output = "Z";}
elsif ($filename =~ /xor/){
    $NumberOfInput =~ s/xor//g;
    $NumberOfInput =~ s/x[\d]+//g;
    $OtherInput = " gnd";
    $output = "Z";}
elsif ($filename =~ /and/){
    $NumberOfInput =~ s/and//g;
    $NumberOfInput =~ s/x[\d]+//g;
    $OtherInput = " vdd";
    $output = "Z";}
elsif ($filename =~ /or/){
    $NumberOfInput =~ s/or//g;
    $NumberOfInput =~ s/x[\d]+//g;
    $OtherInput = " gnd";
    $output = "Z";}

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] .= "\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 ACCT POST %PROBE=1\n.param ttra=591.8p LV=0.2p vdd=3.3\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 = " node_b";

$lastpart = "X".$filename.$I.$OtherInput x $n_input.$O." ".$filename."\n";

$abc = 
"Va_in node_in 0 pulse 0 $V 500p 50p 50p 4n 8n\n".
"vameter node_in $I dc 0\n".
"Gi node_a 0 CUR='i1(vameter)'\n".
"Cref node_b 0 1pF\n".
"Gra node_a 0 VCR pwl(1) $I 0 0,1e-15 '$V * 0.2-0.001',1e-15 '$V * 0.2',\n".
"+1e15 '$V * 0.8',1e15 '$V * 0.8+0.001',1e-15 $V ,1e-15\n".
"Grb node_a node_b VCR pwl(1) $I 0 0,1e15 '$V *0.2-0.001',1e15 '$V * 0.2',\n".
"+1e-15 '$V * 0.8',1e-15 '$V *0.8+0.001',1e15 $V ,1e15\n".
".ic v(node_a) 0\n".
".ic v(node_b) 0\n".
".measure tran vcref_max max v(0,node_b)\n".
".measure cin_a param='(vcref_max * 1e-12)/(0.6 * $V)'\n".
".tran 5p 8n\n";

####################################################
#change .alter
####################################################
@last;
$count = 2;
for (1..$n_input){
	$last[0] = "X$filename";
	$last[1] = $OtherInput;
	for (1..$n_input){
		$last[$_ + 1] = $G;}
	$last[$count++] = $I;
	$last .= ".alter\n@last $O $filename\n";
	}
$last .= ".end\n";

####################################################
#combine all
####################################################

$final = "$top_middle"."\n"."$lastpart"."\n"."$abc"."\n"."$last";
print HSPICE $final;

close HSPICE;






