clock_enable.pl,v #1

  • //
  • guest/
  • robert_yu/
  • autochar-1.5.3/
  • src/
  • RCS/
  • clock_enable.pl,v
  • View
  • Commits
  • Open Download .zip Download (55 KB)
head	1.14;
access;
symbols;
locks; strict;
comment	@# @;


1.14
date	99.06.07.15.02.39;	author ryu;	state Exp;
branches;
next	1.13;

1.13
date	99.01.29.07.32.46;	author ryu;	state Exp;
branches;
next	1.12;

1.12
date	99.01.20.07.44.59;	author ryu;	state Exp;
branches;
next	1.11;

1.11
date	99.01.14.10.19.02;	author ryu;	state Exp;
branches;
next	1.10;

1.10
date	99.01.13.07.18.42;	author ryu;	state Exp;
branches;
next	1.9;

1.9
date	98.09.13.11.09.15;	author ryu;	state Exp;
branches;
next	1.8;

1.8
date	98.09.13.04.14.38;	author ryu;	state Exp;
branches;
next	1.7;

1.7
date	98.09.12.19.54.02;	author ryu;	state Exp;
branches;
next	1.6;

1.6
date	98.09.08.13.16.49;	author ryu;	state Exp;
branches;
next	1.5;

1.5
date	98.09.07.11.17.15;	author ryu;	state Exp;
branches;
next	1.4;

1.4
date	98.09.06.20.43.23;	author ryu;	state Exp;
branches;
next	1.3;

1.3
date	98.09.06.04.18.47;	author ryu;	state Exp;
branches;
next	1.2;

1.2
date	98.09.05.22.10.32;	author ryu;	state Exp;
branches;
next	1.1;

1.1
date	98.09.03.09.08.10;	author ryu;	state Exp;
branches;
next	;


desc
@#! /usr/local/bin/perl
@


1.14
log
@Optional space in measure results
@
text
@#	$Id: clock_enable.pl,v 1.13 1999/01/29 07:32:46 ryu Exp ryu $

#	Copyright (C) 1999 Robert K. Yu
#	email: robert@@yu.org

#	This file is part of Autochar.

#	Autochar is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2, or (at your option)
#	any later version.

#	Autochar is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.

#	You should have received a copy of the GNU General Public License
#	along with Autochar; see the file COPYING.  If not, write to the
#	Free Software Foundation, Inc., 59 Temple Place - Suite 330,
#	Boston, MA 02111-1307, USA.

#   ce_run --
#	Top-level function setup/hold characterization.
#	Generate the spice netlists, run hspice, and extract
#	data.
#
sub ce_run {
    local($d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;

    printf OUT "### CLOCK ENABLE ###########################################################\n\n";
    printf OUT "Cellname:\t\"$cellname\"\n";
    printf OUT "D Input:\t\"$d\"\n";
    printf OUT "Clock Enable:\t\"$ce\"\t($cetype)\n";
    printf OUT "Clock Input:\t\"$clk\"\t($clktype)\n";
    printf OUT "Q Output:\t\"$q\"\t($qtype)\n";
    printf OUT "Critical Node:\t\"$c\"\t($ctype)\n\n";

    # enable setup
    &ces_run ('lh', $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
    &ces_run ('hl', $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);

    # enable hold
    &ceh_run ('lh', $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
    &ceh_run ('hl', $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
}


#------ CLOCK ENABLE SETUP TIME CHARACTERIZATION -------------------------------

sub ces_run {

    my($out_trans, $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;

    local($run_name, $dtrans);
    local($optmod, $optparam, $optmeasure);

    # check
    if (($cetype ne 'active_high') && ($cetype ne 'active_low')) {
	die "ERROR: clock enable type must be either 'active_high' or 'active_low'\n";
    }
    if (($clktype ne 'rising') && ($clktype ne 'falling')) {
	die "ERROR: clock type must be either 'rising' or 'falling'\n";
    }
    if (($qtype ne 'inverting') && ($qtype ne 'non_inverting')) {
	die "ERROR: q type must be either 'inverting' or 'non_inverting'\n";
    }

    # give names to these puppies
    $optmod = 'optmod';
    $optparam = 'optsetup';
    $optmeasure = 'optpass';

    $run_name = &run_file_name($cellname, $ce, $clk, $q, 'ces');
    open(SPICEIN,">$run_name") || die "ERROR:  Cannot open file '$run_name'.";

    # Create the hspice netlist(s)
    &print_header(SPICEIN, '*');
    printf SPICEIN "*	Char:	D-Flop Clock Enable Setup Time Characterization\n";
    printf SPICEIN "*	Data:	\"$d\"\n";
    printf SPICEIN "*	Enable:	\"$ce\"\n";
    printf SPICEIN "*	Clock:	\"$clk\"\n";
    printf SPICEIN "*	Q:	\"$q\"\n";
    printf SPICEIN "*	C:	\"$c\"\n";
    printf SPICEIN "*	Trans:	\"$out_trans\"\n";

    &ces_print_setup (SPICEIN);
    &ces_print_source (SPICEIN, $cetype, $clktype, $out_trans, $qtype);
    &ces_print_dut (SPICEIN, $d, $ce, $clk, $q, $tie, @@tie_list);
    &ces_print_measure (SPICEIN, $clktype, $out_trans, $ctype, $c);
    &ces_print_trans (SPICEIN, $clktype, $out_trans);

    printf SPICEIN ".end\n";
    close(SPICEIN);

    &run_spice($run_name);

    &ces_report_spice($run_name, $out_trans, $ce, $clktype, $clk, $qtype, $q, $ctype, $c);
}


sub ces_print_setup {

    my ($fp) = @@_;

    printf $fp "\n*--- SETUP ---------------------------------------------------\n";
    printf $fp ".include '$techpath/$spice_corner'\n";
    printf $fp ".include '$spice_netlist'\n";
    if ($spice_include ne 'none') {
	printf $fp "$spice_include\n";
    }

    if ($spice_type eq 'smartspice') {
	printf $fp "$smartspice_options\n";
	printf $fp ".param isetup = 0\n" ;
	printf $fp ".param setup_hold_scale = '$setup_hold_scale'\n" ;
	printf $fp ".param setup = 'isetup*setup_hold_scale'\n" ;
    } else {
	printf $fp "$optim_options\n";
	printf $fp ".model $optmod opt method=bisection\n";
	printf $fp "+\trelin=$relin\n";
	printf $fp "+\trelout=$relout\n";
	printf $fp ".param setup = $optparam('$setup_range[0]', '$setup_range[0]', '$setup_range[1]')\n" ;
    }

    if ($#slewrate != -1) {
	printf $fp ".param slewrate = '$slewrate[0]'\n" ;
	printf $fp ".param slew_start = '$start_slew_percent'\n" ;
	printf $fp ".param slew_end = '$end_slew_percent'\n" ;
    }
}


#	Modifies dtrans
#
sub ces_print_source {

    my ($fp, $cetype, $clktype, $out_trans, $qtype) = @@_;

    printf $fp "\n*--- INPUTS --------------------------------------------------\n";

    if ($clktype eq 'rising') {
	if ($#slewrate != -1) {
	    printf $fp "vclk vclk $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_risetime/2'
+	'0'
+	'0'
+	'$trans_pulse_width+$trans_risetime/2+$trans_falltime/2'
+	'$trans_period')\n";
	} else {
	    printf $fp "vclk vclk $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_pulse_width'
+	'$trans_period')\n";
	}
    } elsif ($clktype eq 'falling') {
	if ($#slewrate != -1) {
	    printf $fp "vclk vclk $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_risetime/2'
+	'0'
+	'0'
+	'$trans_pulse_width+$trans_risetime/2+$trans_falltime/2'
+	'$trans_period')\n";
	} else {
	    printf $fp "vclk vclk $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_pulse_width'
+	'$trans_period')\n";
	}
    } else {
	die "ERROR: unknown clock transition type '$clktype'\n";
    }

    if ( (($out_trans eq 'lh') && ($qtype eq 'non_inverting')) ||
	 (($out_trans eq 'hl') && ($qtype eq 'inverting')) ) {
	$dtrans = 'rise';
	printf $fp "vd vd $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    } elsif ( (($out_trans eq 'hl') && ($qtype eq 'non_inverting')) ||
	      (($out_trans eq 'lh') && ($qtype eq 'inverting')) ) {
	$dtrans = 'fall';
	printf $fp "vd vd $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    } else {
	die "ERROR: unknown combination of '$out_trans' and '$qtype'\n";
    }

    if ($cetype eq 'active_high') {
	printf $fp "vce vce $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width/2'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_period-$trans_risetime-$trans_pulse_width/2-setup'
+	'4*$trans_period')\n";
    } elsif ($cetype eq 'active_low') {
	printf $fp "vce vce $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width/2'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_period-$trans_risetime-$trans_pulse_width/2-setup'
+	'4*$trans_period')\n";
    }
}


sub ces_print_dut {

    my($fp, $d, $ce, $clk, $q, $tie, $tie_list) = @@_;
    my($term, $termname, $termtype);
    my($dbuf, $clkbuf, $cebuf, $outload);
    my($vcvs);
    local($term_no, @@vcvs_list, @@output_loads);
    my(@@inlist, @@reflist);

    $term_no = 0;

    if ($buffer{$d} ne '') {
	$dbuf = $buffer{$d};
    } else {
	$dbuf = $buffer{'default'};
    }
    if ($buffer{$ce} ne '') {
	$cebuf = $buffer{$ce};
    } else {
	$cebuf = $buffer{'default'};
    }
    if ($buffer{$clk} ne '') {
	$clkbuf = $buffer{$clk};
    } else {
	$clkbuf = $buffer{'default'};
    }
    if ($#slewrate != -1) {
	$clkbuf = 'slewbuffer';
	printf STDERR "INFO: slewbuffer buffer used for slew rate setup_hold at clock input.\n";
    }


    printf $fp "\n*--- TEST CIRCUIT --------------------------------------------\n";

    @@inlist = ($d, $ce, $clk);
    @@reflist = ('d,', 'ce', 'clk');

    if ($dbuf eq 'none') {
	printf $fp "vshortd vd d DC 0\n";
    } else {
	printf $fp "xdbuf vd d $dbuf\n";
    }
    if ($cebuf eq 'none') {
	printf $fp "vshortce vce ce DC 0\n";
    } else {
	printf $fp "xcebuf vce ce $clkbuf\n";
    }
    if ($clkbuf eq 'none') {
	printf $fp "vshortclk vclk clk DC 0\n";
    } else {
	printf $fp "xclkbuf vclk clk $clkbuf\n";
    }

    printf $fp "xflop\n";
    foreach $term (@@termlist) {
	($termname, $termtype) = split(':', $term);
	if ($termname eq $d) {
	    printf $fp "+\td\t\$ $term\n";
	    next;
	}
	if ($termname eq $ce) {
	    printf $fp "+\tce\t\$ $term\n";
	    next;
	}
	if ($termname eq $clk) {
	    printf $fp "+\tclk\t\$ $term\n";
	    next;
	}
	if ($termname eq $q) {
	    printf $fp "+\t%s\t\$ $term\n", &lookup_output_load($termname, 'q');
	    next;
	}
	if ($termtype eq 'i') {
	    printf $fp "+\t%s\t\$ $term\n",
		&lookup_input($termname, \@@inlist, \@@reflist, $tie, @@tie_list);
	    next;
	}
	if ($termtype eq 'o') {
	    printf $fp "+\t%s\t\$ $term\n", &lookup_output_load($termname);
	    next;
	}
    }
    printf $fp "+\t$cellname\n";

    # if any
    foreach $vcvs (@@vcvs_list) {
	printf $fp "$vcvs\n";
    }

    printf $fp "\n*--- LOADS ---------------------------------------------------\n";
    # if any
    foreach $outload (@@output_loads) {
	printf $fp "$outload\n";
    }
}


sub ces_print_measure {

    my($fp, $clktype, $out_trans, $ctype, $c) = @@_;

    printf $fp "\n*--- MEASURE -------------------------------------------------\n";
    printf $fp ".option autostop\n";

    printf $fp "* Measure setup time:\n";

    if ($spice_type eq 'smartspice') {
	printf $fp ".measure tran isetup param='isetup'\n";
	printf $fp ".measure tran setup param='setup'\n";
    }

    printf $fp ".measure tran setup_${out_trans} %s v(ce) val='$midpoint_value' cross=2\n",
	&trig_word();
    if ($clktype eq 'rising') {
	printf $fp "+\ttarg=v(clk) val='$midpoint_value' rise=2\n";
    } else {
	printf $fp "+\ttarg=v(clk) val='$midpoint_value' fall=2\n";
    }

    printf $fp "* Measure clock slew rate:\n";
    if ($clktype eq 'rising') {
	printf $fp
	    ".measure tran clkslew %s v(clk) val='$slew_r1' rise=2\n";
	    &trig_word();
	printf $fp
	    "+\ttarg=v(clk) val='$slew_r2' rise=2\n";
    } else {
	printf $fp
	    ".measure tran clkslew %s v(clk) val='$slew_f1' fall=2\n";
	    &trig_word();
	printf $fp
	    "+\ttarg=v(clk) val='$slew_f2' fall=2\n";
    }

    printf $fp "\n* Measure internal criterion node:\n";
    printf $fp ".measure tran vcrit find v(xflop.${c})\n";
    if ($clktype eq 'rising') {
	printf $fp "+\twhen v(clk)='$clock_percent*$high_value' rise=2\n"; 
    } else {
	printf $fp "+\twhen v(clk)='(1-$clock_percent)*$high_value' fall=2\n"; 
    }

    # cnode:
    if ( (($dtrans eq 'rise') && ($ctype eq 'inverting')) ||
	 (($dtrans eq 'fall') && ($ctype eq 'non_inverting')) ) {
	printf $fp ".measure tran $optmeasure param='($high_value-vcrit)/$high_value'\n";
	if ($spice_type ne 'smartspice') {
	    printf $fp "+\tgoal='${criterion_percent}'\n";
	}
    } elsif ( (($dtrans eq 'fall') && ($ctype eq 'inverting')) ||
	      (($dtrans eq 'rise') && ($ctype eq 'non_inverting')) ) {
	printf $fp ".measure tran $optmeasure param='vcrit/$high_value'\n";
	if ($spice_type ne 'smartspice') {
	    printf $fp "+\tgoal='${criterion_percent}'\n";
	}
    }
}


sub ces_print_trans {

    my($fp, $clktype, $out_trans) = @@_;
    my($j);

    printf $fp "\n*--- TRANSIENT -----------------------------------------------\n";
    if ($spice_type eq 'smartspice') {

	printf $fp "* Measure final clock->q time:\n";
	if ($clktype eq 'rising') {
	    printf $fp ".measure tran clk_q delay v(clk) val='$midpoint_value' rise=2\n";
	} else {
	    printf $fp ".measure tran clk_q delay v(clk) val='$midpoint_value' fall=2\n";
	}
	if ($out_trans eq 'lh') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
	} elsif ($out_trans eq 'hl') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
	} else {
	    die "ERROR: unknown output transition '$out_trans'\n";
	}
	printf $fp ".trans $trans_timestep '$trans_timestop'\n";

    } else {
	printf $fp ".trans $trans_timestep '$trans_timestop' sweep
+	optimize=$optparam
+	results=$optmeasure
+	model=$optmod\n";

	# Have to put this here in order for bisect to work. A
	# failed measurement during bisect causes bisect to abort.
	printf $fp ".trans $trans_timestep '$trans_timestop'\n";
	printf $fp "\n* Measure final clock->q time:\n";
	if ($clktype eq 'rising') {
	    printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' rise=2\n";
	} else {
	    printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' fall=2\n";
	}

	if ($out_trans eq 'lh') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
	} elsif ($out_trans eq 'hl') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
	} else {
	    die "ERROR: unknown output transition '$out_trans'\n";
	}
    }

    if ($spice_type eq 'smartspice') {
	# common with setup_hold module
	&s_print_control($fp, $out_trans);
    }

    printf $fp "\n* Alter slewrate:\n";
    for ($j = 1; $j <= $#slewrate; $j++) {
	printf $fp ".alter\n";
	printf $fp ".param slewrate = '$slewrate[$j]'\n" ;
    }
}


sub ces_report_spice {

    my  ($run_name, $out_trans, $ce, $clktype, $clk, $qtype, $q, $ctype, $c) = @@_;

    my($base,$dir,$ext,$spiceout);
    my(@@setup, @@clkslew, @@clk_q, @@vcrit, @@pass);
    my(@@scaled_setup, @@scaled_clkslew, @@scaled_clk_q, $i);

    ($base,$dir,$ext) = fileparse($run_name, '\.sp');
    $spiceout = $base . '.out';

    printf STDERR "Extracting results from '$spiceout' ...\n";

    # grab the last values
    open(SPICEOUT, $spiceout) || die "ERROR: Cannot find '$spiceout'.\n";
    if ($spice_type eq 'smartspice') {
	while (<SPICEOUT>) {
	    if (($name, $value) = /^Final (setup_${out_trans}) *= +([0-9\+\-eE\.]+)/) {
		push(@@setup, $value);
		next;
	    }
	    if (($name, $value) = /^Final (clkslew) *= +([0-9\+\-eE\.]+)/) {
		push (@@clkslew, $value);
		next;
	    }
	    if (($name, $value) = /^Final (clk_q) *= +([0-9\+\-eE\.]+)/) {
		push (@@clk_q, $value);
		next;
	    }
	    if (($name, $value) = /^Final (vcrit) *= +([0-9\+\-eE\.]+)/) {
		push (@@vcrit, $value);
		next;
	    }
	    if (($name, $value) = /^Final ($optmeasure) *= +([0-9\+\-eE\.]+)/) {
		push (@@pass, $value);
		next;
	    }
	}
    } else {
	while (<SPICEOUT>) {
	    if (($name, $value) = /^ +(setup_${out_trans}) *= +([0-9\+\-eE\.]+)/) {
		push(@@setup, $value);
		next;
	    }
	    if (($name, $value) = /^ +(clkslew) *= +([0-9\+\-eE\.]+)/) {
		push (@@clkslew, $value);
		next;
	    }
	    if (($name, $value) = /^ +(clk_q) *= +([0-9\+\-eE\.]+)/) {
		push (@@clk_q, $value);
		next;
	    }
	    if (($name, $value) = /^ +(vcrit) *= +([0-9\+\-eE\.]+)/) {
		push (@@vcrit, $value);
		next;
	    }
	    if (($name, $value) = /^ +($optmeasure) *= +([0-9\+\-eE\.]+)/) {
		push (@@pass, $value);
		next;
	    }
	}
    }

    @@setup = &halve_list(@@setup);
    @@clkslew = &halve_list(@@clkslew);
    @@vcrit = &halve_list(@@vcrit);
    @@pass = &halve_list(@@pass);

    printf OUT "\n";
    printf OUT "    InputSlew\tSetup_${out_trans}\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [s]\t\t[s]\t\t[s]\t\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\n";

    for ($i = 0; $i <= $#setup; $i++) {
	printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	    $clkslew[$i], $setup[$i], $clk_q[$i], $vcrit[$i], $pass[$i];
    }

    @@scaled_setup = &div_list($scale_delay, @@setup);
    @@scaled_clk_q = &div_list($scale_delay, @@clk_q);
    @@scaled_clkslew = &div_list($scale_delay, @@clkslew);

    printf OUT "\n";
    printf OUT "    InputSlew\tSetup_${out_trans}\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [scaled]\t[scaled]\t[scaled]\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\n";

    for ($i = 0; $i <= $#setup; $i++) {
	printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	    $scaled_clkslew[$i], $scaled_setup[$i],
	    $scaled_clk_q[$i], $vcrit[$i], $pass[$i];
    }
    printf OUT "\n\n";

    &ces_save_data($cellname, $ce, $cetype, $clk, $clktype, ('setup_' . $out_trans),
	\@@scaled_setup);

    close SPICEOUT;
}

#------ CLOCK ENABLE HOLD TIME CHARACTERIZATION --------------------------------

sub ceh_run {

    my($out_trans, $d, $cetype, $ce, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;

    local($run_name, $dtrans);
    local($optmod, $optparam, $optmeasure);

    # check
    if (($cetype ne 'active_high') && ($cetype ne 'active_low')) {
	die "ERROR: clock enable type must be either 'active_high' or 'active_low'\n";
    }
    if (($clktype ne 'rising') && ($clktype ne 'falling')) {
	die "ERROR: clock type must be either 'rising' or 'falling'\n";
    }
    if (($qtype ne 'inverting') && ($qtype ne 'non_inverting')) {
	die "ERROR: q type must be either 'inverting' or 'non_inverting'\n";
    }

    # give names to these puppies
    $optmod = 'optmod';
    $optparam = 'opthold';
    $optmeasure = 'optpass';

    $run_name = &run_file_name($cellname, $ce, $clk, $q, 'ceh');
    open(SPICEIN,">$run_name") || die "ERROR:  Cannot open file '$run_name'.";

    # Create the hspice netlist(s)
    &print_header(SPICEIN, '*');
    printf SPICEIN "*	Char:	D-Flop Clock Enable Hold Time Characterization\n";
    printf SPICEIN "*	Data:	\"$d\"\n";
    printf SPICEIN "*	Enable:	\"$ce\"\n";
    printf SPICEIN "*	Clock:	\"$clk\"\n";
    printf SPICEIN "*	Q:	\"$q\"\n";
    printf SPICEIN "*	C:	\"$c\"\n";
    printf SPICEIN "*	Trans:	\"$out_trans\"\n";

    &ceh_print_setup (SPICEIN);
    &ceh_print_source (SPICEIN, $cetype, $clktype, $out_trans, $qtype);
    &ceh_print_dut (SPICEIN, $d, $ce, $clk, $q, $tie, @@tie_list);
    &ceh_print_measure (SPICEIN, $clktype, $out_trans, $ctype, $c);
    &ceh_print_trans (SPICEIN, $clktype, $out_trans);

    printf SPICEIN ".end\n";
    close(SPICEIN);

    &run_spice($run_name);

    &ceh_report_spice($run_name, $out_trans, $ce, $clktype, $clk, $qtype, $q, $ctype, $c);
}


sub ceh_print_setup {

    my ($fp) = @@_;

    printf $fp "\n*--- SETUP ---------------------------------------------------\n";
    printf $fp ".include '$techpath/$spice_corner'\n";
    printf $fp ".include '$spice_netlist'\n";
    if ($spice_include ne 'none') {
	printf $fp "$spice_include\n";
    }

    if ($spice_type eq 'smartspice') {
	printf $fp "$smartspice_options\n";
	printf $fp ".param ihold = 0\n" ;
	printf $fp ".param setup_hold_scale = '$setup_hold_scale'\n" ;
	printf $fp ".param hold = 'ihold*setup_hold_scale'\n" ;
    } else {
	printf $fp "$optim_options\n";
	printf $fp ".model $optmod opt method=bisection\n";
	printf $fp "+\trelin=$relin\n";
	printf $fp "+\trelout=$relout\n";
	printf $fp ".param hold = $optparam('$hold_range[0]', '$hold_range[0]', '$hold_range[1]')\n" ;
    }

    if ($#slewrate != -1) {
	printf $fp ".param slewrate = '$slewrate[0]'\n" ;
	printf $fp ".param slew_start = '$start_slew_percent'\n" ;
	printf $fp ".param slew_end = '$end_slew_percent'\n" ;
    }
}


#	Modifies dtrans
#
sub ceh_print_source {

    my ($fp, $cetype, $clktype, $out_trans, $qtype) = @@_;

    printf $fp "\n*--- INPUTS --------------------------------------------------\n";

    if ($clktype eq 'rising') {
	if ($#slewrate != -1) {
	    printf $fp "vclk vclk $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_risetime/2'
+	'0'
+	'0'
+	'$trans_pulse_width+$trans_risetime/2+$trans_falltime/2'
+	'$trans_period')\n";
	} else {
	    printf $fp "vclk vclk $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_pulse_width'
+	'$trans_period')\n";
	}
    } elsif ($clktype eq 'falling') {
	if ($#slewrate != -1) {
	    printf $fp "vclk vclk $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_risetime/2'
+	'0'
+	'0'
+	'$trans_pulse_width+$trans_risetime/2+$trans_falltime/2'
+	'$trans_period')\n";
	} else {
	    printf $fp "vclk vclk $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay'
+	'$trans_risetime'
+	'$trans_falltime'
+	'$trans_pulse_width'
+	'$trans_period')\n";
	}
    } else {
	die "ERROR: unknown clock transition type '$clktype'\n";
    }

    if ( (($out_trans eq 'lh') && ($qtype eq 'non_inverting')) ||
	 (($out_trans eq 'hl') && ($qtype eq 'inverting')) ) {
	$dtrans = 'rise';
	printf $fp "vd vd $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    } elsif ( (($out_trans eq 'hl') && ($qtype eq 'non_inverting')) ||
	      (($out_trans eq 'lh') && ($qtype eq 'inverting')) ) {
	$dtrans = 'fall';
	printf $fp "vd vd $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_risetime+$trans_pulse_width'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    } else {
	die "ERROR: unknown combination of '$out_trans' and '$qtype'\n";
    }

    if ($cetype eq 'active_high') {
	printf $fp "vce vce $low_value pulse (
+	'$high_value'
+	'$low_value'
+	'$trans_delay+$trans_period+hold'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    } elsif ($cetype eq 'active_low') {
	printf $fp "vce vce $low_value pulse (
+	'$low_value'
+	'$high_value'
+	'$trans_delay+$trans_period+hold'
+	'$trans_risetime'
+	'$trans_falltime'
+	'3*$trans_period'
+	'4*$trans_period')\n";
    }
}


sub ceh_print_dut {

    my($fp, $d, $ce, $clk, $q, $tie, $tie_list) = @@_;
    my($term, $termname, $termtype);
    my($dbuf, $clkbuf, $outload);
    my($vcvs);
    local($term_no, @@vcvs_list, @@output_loads);
    my(@@inlist, @@reflist);

    $term_no = 0;

    if ($buffer{$d} ne '') {
	$dbuf = $buffer{$d};
    } else {
	$dbuf = $buffer{'default'};
    }
    if ($buffer{$ce} ne '') {
	$cebuf = $buffer{$ce};
    } else {
	$cebuf = $buffer{'default'};
    }
    if ($buffer{$clk} ne '') {
	$clkbuf = $buffer{$clk};
    } else {
	$clkbuf = $buffer{'default'};
    }
    if ($#slewrate != -1) {
	$clkbuf = 'slewbuffer';
	printf STDERR "INFO: slewbuffer buffer used for slew rate setup_hold at clock input.\n";
    }

    printf $fp "\n*--- TEST CIRCUIT --------------------------------------------\n";

    @@inlist = ($d, $ce, $clk);
    @@reflist = ('d', 'ce', 'clk');

    if ($dbuf eq 'none') {
	printf $fp "vshortd vd d DC 0\n";
    } else {
	printf $fp "xdbuf vd d $dbuf\n";
    }
    if ($cebuf eq 'none') {
	printf $fp "vshortce vce ce DC 0\n";
    } else {
	printf $fp "xcebuf vce ce $clkbuf\n";
    }
    if ($clkbuf eq 'none') {
	printf $fp "vshortclk vclk clk DC 0\n";
    } else {
	printf $fp "xclkbuf vclk clk $clkbuf\n";
    }

    printf $fp "xflop\n";
    foreach $term (@@termlist) {
	($termname, $termtype) = split(':', $term);
	if ($termname eq $d) {
	    printf $fp "+\td\t\$ $term\n";
	    next;
	}
	if ($termname eq $ce) {
	    printf $fp "+\tce\t\$ $term\n";
	    next;
	}
	if ($termname eq $clk) {
	    printf $fp "+\tclk\t\$ $term\n";
	    next;
	}
	if ($termname eq $q) {
	    printf $fp "+\t%s\t\$ $term\n", &lookup_output_load($termname, 'q');
	    next;
	}
	if ($termtype eq 'i') {
	    printf $fp "+\t%s\t\$ $term\n",
		&lookup_input($termname, \@@inlist, \@@reflist, $tie, @@tie_list);
	    next;
	}
	if ($termtype eq 'o') {
	    printf $fp "+\t%s\t\$ $term\n", &lookup_output_load($termname);
	    next;
	}
    }
    printf $fp "+\t$cellname\n";

    # if any
    foreach $vcvs (@@vcvs_list) {
	printf $fp "$vcvs\n";
    }

    printf $fp "\n*--- LOADS ---------------------------------------------------\n";
    # if any
    foreach $outload (@@output_loads) {
	printf $fp "$outload\n";
    }
}


sub ceh_print_measure {

    my($fp, $clktype, $out_trans, $ctype, $c) = @@_;

    printf $fp "\n*--- MEASURE -------------------------------------------------\n";
    printf $fp ".option autostop\n";

    if ($spice_type eq 'smartspice') {
	printf $fp ".measure tran ihold param='ihold'\n";
	printf $fp ".measure tran hold param='hold'\n";
    }

    printf $fp "* Measure hold time:\n";
    if ($clktype eq 'rising') {
	printf $fp ".measure tran hold_${out_trans} %s v(clk) val='$midpoint_value' rise=2\n";
	&trig_word();
    } else {
	printf $fp ".measure tran hold_${out_trans} %s v(clk) val='$midpoint_value' fall=2\n";
	&trig_word();
    }
    printf $fp "+\ttarg=v(ce) val='$midpoint_value' cross=1\n";

    printf $fp "* Measure clock slew rate:\n";
    if ($clktype eq 'rising') {
	printf $fp
	    ".measure tran clkslew %s v(clk) val='$slew_r1' rise=2\n";
	    &trig_word();
	printf $fp
	    "+\ttarg=v(clk) val='$slew_r2' rise=2\n";
    } else {
	printf $fp
	    ".measure tran clkslew %s v(clk) val='$slew_f1' fall=2\n";
	    &trig_word();
	printf $fp
	    "+\ttarg=v(clk) val='$slew_f2' fall=2\n";
    }

    printf $fp "\n* Measure internal criterion node:\n";
    printf $fp ".measure tran vcrit find v(xflop.${c})\n";
    if ($clktype eq 'rising') {
	printf $fp "+\twhen v(clk)='$clock_percent*$high_value' rise=2\n"; 
    } else {
	printf $fp "+\twhen v(clk)='(1-$clock_percent)*$high_value' fall=2\n"; 
    }

    # cnode:
    if ( (($dtrans eq 'rise') && ($ctype eq 'inverting')) ||
	 (($dtrans eq 'fall') && ($ctype eq 'non_inverting')) ) {
	printf $fp ".measure tran $optmeasure param='($high_value-vcrit)/$high_value'\n";
	if ($spice_type ne 'smartspice') {
	    printf $fp "+\tgoal='${criterion_percent}'\n";
	}
    } elsif ( (($dtrans eq 'fall') && ($ctype eq 'inverting')) ||
	      (($dtrans eq 'rise') && ($ctype eq 'non_inverting')) ) {
	printf $fp ".measure tran $optmeasure param='vcrit/$high_value'\n";
	if ($spice_type ne 'smartspice') {
	    printf $fp "+\tgoal='${criterion_percent}'\n";
	}
    }
}


sub ceh_print_trans {

    my($fp, $clktype, $out_trans) = @@_;

    printf $fp "\n*--- TRANSIENT -----------------------------------------------\n";
    if ($spice_type eq 'smartspice') {

	printf $fp "* Measure final clock->q time:\n";
	if ($clktype eq 'rising') {
	    printf $fp ".measure tran clk_q delay v(clk) val='$midpoint_value' rise=2\n";
	} else {
	    printf $fp ".measure tran clk_q delay v(clk) val='$midpoint_value' fall=2\n";
	}
	if ($out_trans eq 'lh') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
	} elsif ($out_trans eq 'hl') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
	} else {
	    die "ERROR: unknown output transition '$out_trans'\n";
	}
	printf $fp ".trans $trans_timestep '$trans_timestop'\n";

    } else {
	printf $fp ".trans $trans_timestep '$trans_timestop' sweep
+	optimize=$optparam
+	results=$optmeasure
+	model=$optmod\n";

	# Have to put this here in order for bisect to work. A
	# failed measurement during bisect causes bisect to abort.
	printf $fp ".trans $trans_timestep '$trans_timestop'\n";
	printf $fp "\n* Measure final clock->q time:\n";
	if ($clktype eq 'rising') {
	    printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' rise=2\n";
	} else {
	    printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' fall=2\n";
	}

	if ($out_trans eq 'lh') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
	} elsif ($out_trans eq 'hl') {
	    printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
	} else {
	    die "ERROR: unknown output transition '$out_trans'\n";
	}
    }

    if ($spice_type eq 'smartspice') {
	# common with setup_hold module
	&h_print_control($fp, $out_trans);
    }

    printf $fp "\n* Alter slewrate:\n";
    for ($j = 1; $j <= $#slewrate; $j++) {
	printf $fp ".alter\n";
	printf $fp ".param slewrate = '$slewrate[$j]'\n" ;
    }
}


sub ceh_report_spice {

    my  ($run_name, $out_trans, $ce, $clktype, $clk, $qtype, $q, $ctype, $c) = @@_;

    my($base,$dir,$ext,$spiceout);
    my(@@hold, @@clkslew, @@clk_q, @@vcrit, @@pass);
    my(@@scaled_hold, @@scaled_clkslew, @@scaled_clk_q, $i);

    ($base,$dir,$ext) = fileparse($run_name, '\.sp');
    $spiceout = $base . '.out';

    printf STDERR "Extracting results from '$spiceout' ...\n";

    # grab the last values
    open(SPICEOUT, $spiceout) || die "ERROR: Cannot find '$spiceout'.\n";
    if ($spice_type eq 'smartspice') {
	while (<SPICEOUT>) {
	    if (($name, $value) = /^Final (hold_${out_trans}) *= +([0-9\+\-eE\.]+)/) {
		push(@@hold, $value);
		next;
	    }
	    if (($name, $value) = /^Final (clkslew) *= +([0-9\+\-eE\.]+)/) {
		push (@@clkslew, $value);
		next;
	    }
	    if (($name, $value) = /^Final (clk_q) *= +([0-9\+\-eE\.]+)/) {
		push (@@clk_q, $value);
		next;
	    }
	    if (($name, $value) = /^Final (vcrit) *= +([0-9\+\-eE\.]+)/) {
		push (@@vcrit, $value);
		next;
	    }
	    if (($name, $value) = /^Final ($optmeasure) *= +([0-9\+\-eE\.]+)/) {
		push (@@pass, $value);
		next;
	    }
	}
    } else {
	while (<SPICEOUT>) {
	    if (($name, $value) = /^ +(hold_${out_trans}) *= +([0-9\+\-eE\.]+)/) {
		push(@@hold, $value);
		next;
	    }
	    if (($name, $value) = /^ +(clkslew) *= +([0-9\+\-eE\.]+)/) {
		push (@@clkslew, $value);
		next;
	    }
	    if (($name, $value) = /^ +(clk_q) *= +([0-9\+\-eE\.]+)/) {
		push(@@clk_q, $value);
		next;
	    }
	    if (($name, $value) = /^ +(vcrit) *= +([0-9\+\-eE\.]+)/) {
		push (@@vcrit, $value);
		next;
	    }
	    if (($name, $value) = /^ +($optmeasure) *= +([0-9\+\-eE\.]+)/) {
		push (@@pass, $value);
		next;
	    }
	}
    }

    @@hold = &halve_list(@@hold);
    @@clkslew = &halve_list(@@clkslew);
    @@vcrit = &halve_list(@@vcrit);
    @@pass = &halve_list(@@pass);

    printf OUT "\n";
    printf OUT "    InputSlew\tHold_${out_trans}\t\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [s]\t\t[s]\t\t[s]\t\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\n";

    for ($i = 0; $i <= $#hold; $i++) {
	printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	    $clkslew[$i], $hold[$i], $clk_q[$i], $vcrit[$i], $pass[$i];
    }

    @@scaled_hold = &div_list($scale_delay, @@hold);
    @@scaled_clk_q = &div_list($scale_delay, @@clk_q);
    @@scaled_clkslew = &div_list($scale_delay, @@clkslew);

    printf OUT "\n";
    printf OUT "    InputSlew\tHold_${out_trans}\t\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [scaled]\t[scaled]\t[scaled]\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\n";

    for ($i = 0; $i <= $#hold; $i++) {
	printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	    $scaled_clkslew[$i], $scaled_hold[$i],
	    $scaled_clk_q[$i], $vcrit[$i], $pass[$i];
    }
    printf OUT "\n\n";

    &ceh_save_data($cellname, $ce, $cetype, $clk, $clktype, (hold_ . $out_trans),
	\@@scaled_hold);

    close SPICEOUT;
}


1;
@


1.13
log
@Integrated smartspice
@
text
@d1 1
a1 1
#	$Id: clock_enable.pl,v 1.12 1999/01/20 07:44:59 ryu Exp ryu $
d471 1
a471 1
	    if (($name, $value) = /^Final (setup_${out_trans}) += +([0-9\+\-eE\.]+)/) {
d475 1
a475 1
	    if (($name, $value) = /^Final (clkslew) += +([0-9\+\-eE\.]+)/) {
d479 1
a479 1
	    if (($name, $value) = /^Final (clk_q) += +([0-9\+\-eE\.]+)/) {
d483 1
a483 1
	    if (($name, $value) = /^Final (vcrit) += +([0-9\+\-eE\.]+)/) {
d487 1
a487 1
	    if (($name, $value) = /^Final ($optmeasure) += +([0-9\+\-eE\.]+)/) {
d494 1
a494 1
	    if (($name, $value) = /^ +(setup_${out_trans}) += +([0-9\+\-eE\.]+)/) {
d498 1
a498 1
	    if (($name, $value) = /^ +(clkslew) += +([0-9\+\-eE\.]+)/) {
d502 1
a502 1
	    if (($name, $value) = /^ +(clk_q) += +([0-9\+\-eE\.]+)/) {
d506 1
a506 1
	    if (($name, $value) = /^ +(vcrit) += +([0-9\+\-eE\.]+)/) {
d510 1
a510 1
	    if (($name, $value) = /^ +($optmeasure) += +([0-9\+\-eE\.]+)/) {
d974 1
a974 1
	    if (($name, $value) = /^Final (hold_${out_trans}) += +([0-9\+\-eE\.]+)/) {
d978 1
a978 1
	    if (($name, $value) = /^Final (clkslew) += +([0-9\+\-eE\.]+)/) {
d982 1
a982 1
	    if (($name, $value) = /^Final (clk_q) += +([0-9\+\-eE\.]+)/) {
d986 1
a986 1
	    if (($name, $value) = /^Final (vcrit) += +([0-9\+\-eE\.]+)/) {
d990 1
a990 1
	    if (($name, $value) = /^Final ($optmeasure) += +([0-9\+\-eE\.]+)/) {
d997 1
a997 1
	    if (($name, $value) = /^ +(hold_${out_trans}) += +([0-9\+\-eE\.]+)/) {
d1001 1
a1001 1
	    if (($name, $value) = /^ +(clkslew) += +([0-9\+\-eE\.]+)/) {
d1005 1
a1005 1
	    if (($name, $value) = /^ +(clk_q) += +([0-9\+\-eE\.]+)/) {
d1009 1
a1009 1
	    if (($name, $value) = /^ +(vcrit) += +([0-9\+\-eE\.]+)/) {
d1013 1
a1013 1
	    if (($name, $value) = /^ +($optmeasure) += +([0-9\+\-eE\.]+)/) {
@


1.12
log
@No perl header
@
text
@d1 1
a1 1
#	$Id: clock_enable.pl,v 1.11 1999/01/14 10:19:02 ryu Exp ryu $
d112 13
a124 5
    printf $fp "$optim_options\n";
    printf $fp ".model $optmod opt method=bisection\n";
    printf $fp "+\trelin=$relin\n";
    printf $fp "+\trelout=$relout\n";
    printf $fp ".param setup = $optparam('$setup_range[0]', '$setup_range[0]', '$setup_range[1]')\n" ;
d339 8
a346 1
    printf $fp ".measure tran setup_${out_trans} trig=v(ce) val='$midpoint_value' cross=2\n";
d356 2
a357 1
	    ".measure tran clkslew trig=v(clk) val='$slew_r1' rise=2\n";
d362 2
a363 1
	    ".measure tran clkslew trig=v(clk) val='$slew_f1' fall=2\n";
d380 3
a382 1
	printf $fp "+\tgoal='${criterion_percent}'\n";
d386 3
a388 1
	printf $fp "+\tgoal='${criterion_percent}'\n";
d399 19
a417 1
    printf $fp ".trans $trans_timestep '$trans_timestop' sweep
d422 17
a438 8
    # Have to put this here in order for bisect to work. A
    # failed measurement during bisect causes bisect to abort.
    printf $fp ".trans $trans_timestep '$trans_timestop'\n";
    printf $fp "\n* Measure final clock->q time:\n";
    if ($clktype eq 'rising') {
	printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' rise=2\n";
    } else {
	printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' fall=2\n";
d441 3
a443 6
    if ($out_trans eq 'lh') {
	printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
    } elsif ($out_trans eq 'hl') {
	printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
    } else {
	die "ERROR: unknown output transition '$out_trans'\n";
d469 45
a513 20
    while (<SPICEOUT>) {
	if (($name, $value) = /^ +(setup_${out_trans}) += +([0-9\+\-eE\.]+)/) {
	    push(@@setup, $value);
	    next;
	}
	if (($name, $value) = /^ +(clkslew) += +([0-9\+\-eE\.]+)/) {
	    push (@@clkslew, $value);
	    next;
	}
	if (($name, $value) = /^ +(clk_q) += +([0-9\+\-eE\.]+)/) {
	    push (@@clk_q, $value);
	    next;
	}
	if (($name, $value) = /^ +(vcrit) += +([0-9\+\-eE\.]+)/) {
	    push (@@vcrit, $value);
	    next;
	}
	if (($name, $value) = /^ +($optmeasure) += +([0-9\+\-eE\.]+)/) {
	    push (@@pass, $value);
	    next;
d617 13
a629 5
    printf $fp "$optim_options\n";
    printf $fp ".model $optmod opt method=bisection\n";
    printf $fp "+\trelin=$relin\n";
    printf $fp "+\trelout=$relout\n";
    printf $fp ".param hold = $optparam('$hold_range[0]', '$hold_range[0]', '$hold_range[1]')\n" ;
d842 5
d849 2
a850 1
	printf $fp ".measure tran hold_${out_trans} trig=v(clk) val='$midpoint_value' rise=2\n";
d852 2
a853 1
	printf $fp ".measure tran hold_${out_trans} trig=v(clk) val='$midpoint_value' fall=2\n";
d860 2
a861 1
	    ".measure tran clkslew trig=v(clk) val='$slew_r1' rise=2\n";
d866 2
a867 1
	    ".measure tran clkslew trig=v(clk) val='$slew_f1' fall=2\n";
d884 3
a886 1
	printf $fp "+\tgoal='${criterion_percent}'\n";
d890 3
a892 1
	printf $fp "+\tgoal='${criterion_percent}'\n";
d902 19
a920 1
    printf $fp ".trans $trans_timestep '$trans_timestop' sweep
d925 17
a941 8
    # Have to put this here in order for bisect to work. A
    # failed measurement during bisect causes bisect to abort.
    printf $fp ".trans $trans_timestep '$trans_timestop'\n";
    printf $fp "\n* Measure final clock->q time:\n";
    if ($clktype eq 'rising') {
	printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' rise=2\n";
    } else {
	printf $fp ".measure tran clk_q trig=v(clk) val='$midpoint_value' fall=2\n";
d944 3
a946 6
    if ($out_trans eq 'lh') {
	printf $fp "+\ttarg=v(q) val='$midpoint_value' rise=1\n";
    } elsif ($out_trans eq 'hl') {
	printf $fp "+\ttarg=v(q) val='$midpoint_value' fall=1\n";
    } else {
	die "ERROR: unknown output transition '$out_trans'\n";
d972 45
a1016 20
    while (<SPICEOUT>) {
	if (($name, $value) = /^ +(hold_${out_trans}) += +([0-9\+\-eE\.]+)/) {
	    push(@@hold, $value);
	    next;
	}
	if (($name, $value) = /^ +(clkslew) += +([0-9\+\-eE\.]+)/) {
	    push (@@clkslew, $value);
	    next;
	}
	if (($name, $value) = /^ +(clk_q) += +([0-9\+\-eE\.]+)/) {
	    push(@@clk_q, $value);
	    next;
	}
	if (($name, $value) = /^ +(vcrit) += +([0-9\+\-eE\.]+)/) {
	    push (@@vcrit, $value);
	    next;
	}
	if (($name, $value) = /^ +($optmeasure) += +([0-9\+\-eE\.]+)/) {
	    push (@@pass, $value);
	    next;
@


1.11
log
@Using /usr/bin/perl
@
text
@d1 1
a1 3
#! /usr/bin/perl

#	$Id: clock_enable.pl,v 1.10 1999/01/13 07:18:42 ryu Exp ryu $
@


1.10
log
@GPL
@
text
@d1 1
a1 1
#! /usr/local/bin/perl
d3 1
a3 1
#	$Id$
@


1.9
log
@wip
@
text
@d3 1
a3 5
#	Copyright (c) 1998-2001, Robert K. Yu.  All Rights Reserved.
#
#	No part of this program may be used, reproduced, stored in a 
#	retrieval system, or transmitted in any form or by any 
#	means without the prior permission of the author.
d5 2
a6 3
#	$Id: clock_enable.pl,v 1.8 1998/09/13 04:14:38 ryu Exp ryu $
#	Clock Enable Setup/Hold Flop Characterization Functions (2 cycles)
#	Author: Robert K. Yu
d8 16
@


1.8
log
@Added slew rate check on clock enable
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.7 1998/09/12 19:54:02 ryu Exp ryu $
d98 1
a98 1
    printf $fp ".include '$techpath/$spice_orner'\n";
d467 2
d900 1
@


1.7
log
@Added slew-rate to setup and hold; support for non-linear models for clock-q
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.6 1998/09/08 13:16:49 ryu Exp ryu $
d108 6
d126 11
a136 1
	printf $fp "vclk vclk $low_value pulse (
d144 1
d146 11
a156 1
	printf $fp "vclk vclk $low_value pulse (
d164 1
d243 5
d329 13
d366 1
a373 4
    printf $fp "\n\n* Final value:\n";
    printf $fp ".alter\n";
    printf $fp ".trans $trans_timestep '$trans_timestop'\n";

d376 1
d391 6
d405 2
a406 1
    my($setup, $clk_q, $vcrit, $pass);
d417 5
a421 1
	    $setup = $value;
d425 1
a425 1
	    $clk_q = $value;
d429 1
a429 1
	    $vcrit = $value;
d433 1
a433 1
	    $pass = $value;
d438 5
d444 12
a455 7
    printf OUT "    Setup_${out_trans}\tSetup_${out_trans}\tClock-Q\t\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [s]\t\t[scaled]\t\t[s]\t\t[scaled]\t\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\t----------\n";
    printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	$setup, $setup/$scale_delay,
	$clk_q, $clk_q/$scale_delay,
	$vcrit, $pass;
d457 10
d468 1
a468 1
	$setup/$scale_delay);
d541 6
d559 11
a569 1
	printf $fp "vclk vclk $low_value pulse (
d577 1
d579 11
a589 1
	printf $fp "vclk vclk $low_value pulse (
d597 1
d676 4
d761 13
a804 4
    printf $fp "\n\n* Final value:\n";
    printf $fp ".alter\n";
    printf $fp ".trans $trans_timestep '$trans_timestop'\n";

d807 1
d822 6
d836 2
a837 1
    my($hold, $clk_q, $vcrit, $pass);
d848 5
a852 1
	    $hold = $value;
d856 1
a856 1
	    $clk_q = $value;
d860 1
a860 1
	    $vcrit = $value;
d864 1
a864 1
	    $pass = $value;
d869 5
d875 23
a897 7
    printf OUT "    Hold_${out_trans}\tHold_${out_trans}\t\tClock-Q\t\tClock-Q\t\tCritNode\tCritPercent\n";
    printf OUT "    [s]\t\t[scaled]\t\t[s]\t\t[scaled]\t\t[V]\n";
    printf OUT "    ----------\t----------\t----------\t----------\t----------\t----------\n";
    printf OUT "    %.4e\t%.4e\t%.4e\t%.4e\t%.4e\t%.4e\n",
	$hold, $hold/$scale_delay,
	$clk_q, $clk_q/$scale_delay,
	$vcrit, $pass;
d900 1
a900 1
	$hold/$scale_delay);
d904 1
@


1.6
log
@slew rate at the clock input of setup_hold (wip)
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.5 1998/09/07 11:17:15 ryu Exp ryu $
d22 1
d98 1
a98 1
    printf $fp ".include '$init{'techpath'}/$init{'corner'}'\n";
d100 2
a101 2
    if ($init{'include'} ne 'none') {
	printf $fp "$init{'include'}\n";
d103 1
a103 1
    printf $fp "$optim{'options'}\n";
d120 8
a127 8
	printf $fp "vclk vclk $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'pulse_width'}'
+	'$trans{'period'}')\n";
d129 8
a136 8
	printf $fp "vclk vclk $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'pulse_width'}'
+	'$trans{'period'}')\n";
d144 8
a151 8
	printf $fp "vd vd $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d155 8
a162 8
	printf $fp "vd vd $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d168 8
a175 8
	printf $fp "vce vce $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}/2'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'period'}-$trans{'risetime'}-$trans{'pulse_width'}/2-setup'
+	'4*$trans{'period'}')\n";
d177 8
a184 8
	printf $fp "vce vce $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}/2'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'period'}-$trans{'risetime'}-$trans{'pulse_width'}/2-setup'
+	'4*$trans{'period'}')\n";
d289 1
a289 1
    printf $fp ".measure tran setup_${out_trans} trig=v(ce) val='$init{'midpoint'}' cross=2\n";
d291 1
a291 1
	printf $fp "+\ttarg=v(clk) val='$init{'midpoint'}' rise=2\n";
d293 1
a293 1
	printf $fp "+\ttarg=v(clk) val='$init{'midpoint'}' fall=2\n";
d299 1
a299 1
	printf $fp "+\twhen v(clk)='$clock_percent*$init{'high'}' rise=2\n"; 
d301 1
a301 1
	printf $fp "+\twhen v(clk)='(1-$clock_percent)*$init{'high'}' fall=2\n"; 
d307 1
a307 1
	printf $fp ".measure tran $optmeasure param='($init{'high'}-vcrit)/$init{'high'}'\n";
d311 1
a311 1
	printf $fp ".measure tran $optmeasure param='vcrit/$init{'high'}'\n";
d322 1
a322 1
    printf $fp ".trans $trans{'timestep'} '$trans{'timestop'}' sweep
d329 1
a329 1
    printf $fp ".trans $trans{'timestep'} '$trans{'timestop'}'\n";
d335 1
a335 1
	printf $fp ".measure tran clk_q trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d337 1
a337 1
	printf $fp ".measure tran clk_q trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d341 1
a341 1
	printf $fp "+\ttarg=v(q) val='$init{'midpoint'}' rise=1\n";
d343 1
a343 1
	printf $fp "+\ttarg=v(q) val='$init{'midpoint'}' fall=1\n";
d385 1
a385 1
    printf OUT "    [s]\t\t[gates]\t\t[s]\t\t[gates]\t\t[V]\n";
d388 2
a389 2
	$setup, $setup/$init{'scale_delay'},
	$clk_q, $clk_q/$init{'scale_delay'},
d393 1
a393 1
	$setup/$init{'scale_delay'});
d456 1
a456 1
    printf $fp ".include '$init{'techpath'}/$init{'corner'}'\n";
d458 2
a459 2
    if ($init{'include'} ne 'none') {
	printf $fp "$init{'include'}\n";
d461 1
a461 1
    printf $fp "$optim{'options'}\n";
d478 8
a485 8
	printf $fp "vclk vclk $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'pulse_width'}'
+	'$trans{'period'}')\n";
d487 8
a494 8
	printf $fp "vclk vclk $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'$trans{'pulse_width'}'
+	'$trans{'period'}')\n";
d502 8
a509 8
	printf $fp "vd vd $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d513 8
a520 8
	printf $fp "vd vd $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}+$trans{'risetime'}+$trans{'pulse_width'}'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d526 8
a533 8
	printf $fp "vce vce $init{'low'} pulse (
+	'$init{'high'}'
+	'$init{'low'}'
+	'$trans{'delay'}+$trans{'period'}+hold'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d535 8
a542 8
	printf $fp "vce vce $init{'low'} pulse (
+	'$init{'low'}'
+	'$init{'high'}'
+	'$trans{'delay'}+$trans{'period'}+hold'
+	'$trans{'risetime'}'
+	'$trans{'falltime'}'
+	'3*$trans{'period'}'
+	'4*$trans{'period'}')\n";
d648 1
a648 1
	printf $fp ".measure tran hold_${out_trans} trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d650 1
a650 1
	printf $fp ".measure tran hold_${out_trans} trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d652 1
a652 1
    printf $fp "+\ttarg=v(ce) val='$init{'midpoint'}' cross=1\n";
d657 1
a657 1
	printf $fp "+\twhen v(clk)='$clock_percent*$init{'high'}' rise=2\n"; 
d659 1
a659 1
	printf $fp "+\twhen v(clk)='(1-$clock_percent)*$init{'high'}' fall=2\n"; 
d665 1
a665 1
	printf $fp ".measure tran $optmeasure param='($init{'high'}-vcrit)/$init{'high'}'\n";
d669 1
a669 1
	printf $fp ".measure tran $optmeasure param='vcrit/$init{'high'}'\n";
d680 1
a680 1
    printf $fp ".trans $trans{'timestep'} '$trans{'timestop'}' sweep
d687 1
a687 1
    printf $fp ".trans $trans{'timestep'} '$trans{'timestop'}'\n";
d693 1
a693 1
	printf $fp ".measure tran clk_q trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d695 1
a695 1
	printf $fp ".measure tran clk_q trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d699 1
a699 1
	printf $fp "+\ttarg=v(q) val='$init{'midpoint'}' rise=1\n";
d701 1
a701 1
	printf $fp "+\ttarg=v(q) val='$init{'midpoint'}' fall=1\n";
d743 1
a743 1
    printf OUT "    [s]\t\t[gates]\t\t[s]\t\t[gates]\t\t[V]\n";
d746 2
a747 2
	$hold, $hold/$init{'scale_delay'},
	$clk_q, $clk_q/$init{'scale_delay'},
d751 1
a751 1
	$hold/$init{'scale_delay'});
@


1.5
log
@comment
@
text
@d3 1
a3 1
#	Copyright (c) 1998, Robert K. Yu.  All Rights Reserved.
d9 1
a9 1
#	$Id: clock_enable.pl,v 1.4 1998/09/06 20:43:23 ryu Exp ryu $
d86 1
a86 1
    &ces_run_spice($run_name);
a348 17
sub ces_run_spice {

    my($run_name) = @@_;
    my($base,$dir,$type,$spiceout);

    ($base,$dir,$type) = fileparse($run_name, '\.sp');
    $spiceout = $base . '.out';

    # Run hspice
    if ($skip && (-e $spiceout)) {
	printf STDERR "Found \"%s\", skipping run.\n", $spiceout;
    } else {
	printf STDERR "Running %s on \"%s\" ...\n", $init{'spice_cmd'}, $run_name;
	`$init{'spice_cmd'} $run_name`;
    }
}

d444 1
a444 1
    &ceh_run_spice($run_name);
a705 17

sub ceh_run_spice {

    my($run_name) = @@_;
    my($base,$dir,$type,$spiceout);

    ($base,$dir,$type) = fileparse($run_name, '\.sp');
    $spiceout = $base . '.out';

    # Run hspice
    if ($skip && (-e $spiceout)) {
	printf STDERR "Found \"%s\", skipping run.\n", $spiceout;
    } else {
	printf STDERR "Running %s on \"%s\" ...\n", $init{'spice_cmd'}, $run_name;
	`$init{'spice_cmd'} $run_name`;
    }
}
@


1.4
log
@clock enable
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.3 1998/09/06 04:18:47 ryu Exp ryu $
d39 1
a39 1
#------ SETUP TIME CHARACTERIZATION --------------------------------------------
d414 1
a414 1
#------ HOLD TIME CHARACTERIZATION ---------------------------------------------
@


1.3
log
@wip
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.2 1998/09/05 22:10:32 ryu Exp ryu $
d64 1
a64 1
    $run_name = &run_file_name($cellname, $d, $ce, $clk, $q, 's');
d240 1
a240 1
	    printf $fp "+\td\n";
d244 1
a244 1
	    printf $fp "+\tce\n";
d248 1
a248 1
	    printf $fp "+\tclk\n";
d252 1
a252 1
	    printf $fp "+\t%s\n", &lookup_output_load($termname, 'q');
d256 1
a256 1
	    printf $fp "+\t%s\n",
d261 1
a261 1
	    printf $fp "+\t%s\n", &lookup_output_load($termname);
d288 1
a288 1
    printf $fp ".meas tran setup_${out_trans} trig=v(ce) val='$init{'midpoint'}' cross=1\n";
d296 1
a296 1
    printf $fp ".meas tran vcrit find v(xflop.${c})\n";
d303 1
a303 1
    # falling cnode:
d306 1
a306 1
	printf $fp ".meas tran $optmeasure param='($init{'high'}-vcrit)/$init{'high'}'\n";
d310 1
a310 1
	printf $fp ".meas tran $optmeasure param='vcrit/$init{'high'}'\n";
d334 1
a334 1
	printf $fp ".meas tran clk_q trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d336 1
a336 1
	printf $fp ".meas tran clk_q trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d408 1
a408 1
    &ces_save_data($cellname, $ce, $clk, $clktype, ('setup_' . $out_trans),
d439 1
a439 1
    $run_name = &run_file_name($cellname, $d, $ce, $clk, $q, 'h');
d615 1
a615 1
	    printf $fp "+\td\n";
d619 1
a619 1
	    printf $fp "+\tce\n";
d623 1
a623 1
	    printf $fp "+\tclk\n";
d627 1
a627 1
	    printf $fp "+\t%s\n", &lookup_output_load($termname, 'q');
d631 1
a631 1
	    printf $fp "+\t%s\n",
d636 1
a636 1
	    printf $fp "+\t%s\n", &lookup_output_load($termname);
d664 1
a664 1
	printf $fp ".meas tran hold_${out_trans} trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d666 1
a666 1
	printf $fp ".meas tran hold_${out_trans} trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d671 1
a671 1
    printf $fp ".meas tran vcrit find v(xflop.${c})\n";
d678 1
a678 1
    # falling cnode:
d681 1
a681 1
	printf $fp ".meas tran $optmeasure param='($init{'high'}-vcrit)/$init{'high'}'\n";
d685 1
a685 1
	printf $fp ".meas tran $optmeasure param='vcrit/$init{'high'}'\n";
d709 1
a709 1
	printf $fp ".meas tran clk_q trig=v(clk) val='$init{'midpoint'}' rise=2\n";
d711 1
a711 1
	printf $fp ".meas tran clk_q trig=v(clk) val='$init{'midpoint'}' fall=2\n";
d783 1
a783 1
    &ceh_save_data($cellname, $ce, $clk, $clktype, (hold_ . $out_trans),
@


1.2
log
@Consolidate lookup_input functions into one, using list of names and refnames.
@
text
@d9 1
a9 1
#	$Id: clock_enable.pl,v 1.1 1998/09/03 09:08:10 ryu Exp ryu $
d88 1
a88 1
    &ces_report_spice($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c);
d173 1
a173 1
+	'$trans{'period'}-$trans{'pulse_width'}/2-setup'
d182 1
a182 1
+	'$trans{'period'}-$trans{'pulse_width'}/2-setup'
a184 1

d288 1
a288 1
    printf $fp ".meas tran setup_${out_trans} trig=v(d) val='$init{'midpoint'}' cross=1\n";
d368 1
a368 1
    my  ($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c) = @@_;
d408 1
a408 1
    &ces_save_data($cellname, $d, $clk, $clktype, ('setup_' . $out_trans),
d454 1
a454 1
    &ceh_print_dut (SPICEIN, $d, $clk, $q, $tie, @@tie_list);
d463 1
a463 1
    &ceh_report_spice($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c);
d540 20
d565 1
a565 1
    my($fp, $d, $clk, $q, $tie, $tie_list) = @@_;
d570 1
d579 5
d600 5
d618 4
d668 1
a668 1
    printf $fp "+\ttarg=v(d) val='$init{'midpoint'}' cross=2\n";
d743 1
a743 1
    my  ($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c) = @@_;
d783 1
a783 1
    &ceh_save_data($cellname, $d, $clk, $clktype, (hold_ . $out_trans),
@


1.1
log
@entered into RCS
@
text
@d9 2
a10 2
#	$Id: setup_hold.pl,v 1.18 1998/09/01 04:49:20 ryu Exp $
#	Setup/Hold Flop Characterization Functions
d20 1
a20 1
    local($d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;
d24 1
d29 7
a35 7
    # enable
    &en_run ('lh', $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
    &en_run ('hl', $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);

    # disable
    &dis_run ('lh', $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
    &dis_run ('hl', $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list);
d41 1
a41 1
sub en_run {
d43 1
a43 1
    my($out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;
d49 3
d64 1
a64 1
    $run_name = &run_file_name($cellname, $d, $clk, $q, 's');
d69 1
a69 1
    printf SPICEIN "*	Char:	D-Flop Setup Time Characterization\n";
d71 1
d77 5
a81 5
    &en_print_setup (SPICEIN);
    &en_print_source (SPICEIN, $clktype, $out_trans, $qtype);
    &en_print_dut (SPICEIN, $d, $clk, $q, $tie, @@tie_list);
    &en_print_measure (SPICEIN, $clktype, $out_trans, $ctype, $c);
    &en_print_trans (SPICEIN, $clktype, $out_trans);
d86 1
a86 1
    &en_run_spice($run_name);
d88 1
a88 1
    &en_report_spice($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c);
d92 1
a92 1
sub en_print_setup {
d112 1
a112 1
sub en_print_source {
d114 1
a114 1
    my ($fp, $clktype, $out_trans, $qtype) = @@_;
a141 1

d146 1
a146 1
+	'$trans{'delay'}+$trans{'risetime'}+2*$trans{'pulse_width'}+$trans{'falltime'}-setup'
a150 1

a152 1

d157 1
a157 1
+	'$trans{'delay'}+$trans{'risetime'}+2*$trans{'pulse_width'}+$trans{'falltime'}-setup'
a161 1

d165 21
d189 1
a189 1
sub en_print_dut {
d191 1
a191 1
    my($fp, $d, $clk, $q, $tie, $tie_list) = @@_;
d193 2
a194 2
    my($dbuf, $clkbuf, $outload);
    my($vcvs, $drefname, $clkrefname);
d196 1
d205 5
d218 2
a219 2
    $drefname = 'd';
    $clkrefname = 'clk';
d226 5
d244 4
d258 1
a258 1
		&lookup_input_2($termname, $d, $clk, $drefname, $clkrefname, $tie, @@tie_list);
d281 1
a281 1
sub en_print_measure {
d317 1
a317 1
sub en_print_trans {
d350 1
a350 1
sub en_run_spice {
d367 1
a367 1
sub en_report_spice {
d409 1
a409 1
    &en_save_data($cellname, $d, $clk, $clktype, ('setup_' . $out_trans),
d417 1
a417 1
sub dis_run {
d419 1
a419 1
    my($out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c, $tie, @@tie_list) = @@_;
d425 3
d440 1
a440 1
    $run_name = &run_file_name($cellname, $d, $clk, $q, 'h');
d445 1
a445 1
    printf SPICEIN "*	Char:	D-Flop Hold Time Characterization\n";
d447 1
d453 5
a457 5
    &dis_print_setup (SPICEIN);
    &dis_print_source (SPICEIN, $clktype, $out_trans, $qtype);
    &dis_print_dut (SPICEIN, $d, $clk, $q, $tie, @@tie_list);
    &dis_print_measure (SPICEIN, $clktype, $out_trans, $ctype, $c);
    &dis_print_trans (SPICEIN, $clktype, $out_trans);
d462 1
a462 1
    &dis_run_spice($run_name);
d464 1
a464 1
    &dis_report_spice($run_name, $out_trans, $d, $clktype, $clk, $qtype, $q, $ctype, $c);
d468 1
a468 1
sub dis_print_setup {
d488 1
a488 1
sub dis_print_source {
d490 1
a490 1
    my ($fp, $clktype, $out_trans, $qtype) = @@_;
a517 1

d525 1
a525 1
+	'$trans{'pulse_width'}+hold'
a526 1

a528 1

d536 1
a536 1
+	'$trans{'pulse_width'}+hold'
a537 1

d544 1
a544 1
sub dis_print_dut {
d549 1
a549 1
    my($vcvs, $drefname, $clkrefname);
d567 2
a568 2
    $drefname = 'd';
    $clkrefname = 'clk';
d598 1
a598 1
		&lookup_input_2($termname, $d, $clk, $drefname, $clkrefname, $tie, @@tie_list);
d621 1
a621 1
sub dis_print_measure {
d657 1
a657 1
sub dis_print_trans {
d690 1
a690 1
sub dis_run_spice {
d707 1
a707 1
sub dis_report_spice {
d749 1
a749 1
    &dis_save_data($cellname, $d, $clk, $clktype, (hold_ . $out_trans),
@
# Change User Description Committed
#1 6489 robert_yu Saved here.