#!/usr/bin/perl
# Nelson Hu
# EE464H
# 08/06/03

#######################################################
# This program creates Hspice code to be run for Transient analysis

#######################################################
# How to use this program:
# at the folder where "si.inp" (Spectre netlist) is located
# type
#     perl /home/projects/abraham/vlsi464/spicetest/FinalTOOLS/TransientHspice.pl si.inp

#######################################################
# input:
#  si.inp

#######################################################
# output:
#  TRANS_%CELLNAME%.sp

#######################################################
# 1)get the cell name (located in si.inp) for $filename
# 2)open a file named TRANS_%CELLNAME%.sp
#######################################################
@line = <>;
foreach (@line){
	if ($_ =~ /Design cell name:/){
		@temp = split / /,$_;
		$filename = $temp[$#temp];
		chomp $filename;}}

$trans = "TRANS_"."$filename";
open TRANS, ">$trans.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
#
# this section needs to be added for new type of logic cells
#######################################################

$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
#######################################################
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;

$T_top = "\*".$filename.".sp\n.options SPICE NOMOD AUTOSTOP ACCT POST \%PROBE=1\n.param ttra=591.8p LV=0.2p\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";

$lastpart2 = "X".$filename.$OtherInput x $n_input.$I.$O." ".$filename."\nCLOAD".$O.$G." LV\n\nVa".$I.$G." PULSE\(0,3.3,1n,Ttra,Ttra,6n,12n\)\n\nvdd".$V.$G." 3.3\n\n";

$T_final = "$T_top"."\n"."$lastpart2".".tran 0.002n 18n\n.dc va 0 3.3 0.01\n.end\n";

#######################################################
# prints the script to the appropriate file. close the file
#######################################################
print TRANS $T_final;
close TRANS;













































