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 () { 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 () { 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 () { 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 () { 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 () { 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 () { 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), @