#include #include typedef struct { char *name; double *vals; double hl_t; double lh_t; double tphl; double tplh; } Signal; struct { int nv; int np; Signal *sigs; } plot; typedef struct { double w, l; } TranSz; double midpoint; Signal *timev, *in1, *in2, *in3, *out1, *out2, *out3, *out4; main( argc, argv ) int argc; char *argv[]; { FILE *fi = stdin; TranSz p, n; double cap; int i; cap = p.w = p.l = n.w = n.l = -1; for( i = 1; i < argc; i++ ) { if( argv[i][0] == '-' ) { switch( argv[i][1] ) { case 'c' : i++; if( i >= argc ) usage( "missing argument :" ); if( sscanf( argv[i], "%lf", &cap ) != 1 || cap <= 0 ) usage( "bad argument for 'c': " ); cap *= 1E-15; /* convert to ff */ break; case 'n' : i++; if( i >= argc ) usage( "missing argument :" ); if( sscanf( argv[i], "%lf,%lf", &n.w, &n.l ) != 2 || n.w <= 0 || n.l <= 0 ) usage( "bad argument for 'n': " ); break; case 'p' : i++; if( i >= argc ) usage( "missing argument :" ); if( sscanf( argv[i], "%lf,%lf", &p.w, &p.l ) != 2 || p.w <= 0 || p.l <= 0 ) usage( "bad argument for 'p': " ); break; default : usage( "unknown switch :" ); } } else { if( (fi = fopen( argv[i], "r" )) == NULL ) usage( "can not open input file :" ); } } if( cap <= 0 || n.l <= 0 || n.w <= 0 || p.l <= 0 || p.w <= 0 ) usage( "i am missing parameters:" ); if( read_header( fi ) == 0 ) exit( 1 ); if( read_variables( fi ) == 0 ) exit( 1 ); if( read_values( fi ) == 0 ) exit( 1 ); if( find_delays() == 0 ) exit( 1 ); PrintResistEntries( cap, &n, &p ); exit( 0 ); } usage( s ) char *s; { fprintf( stderr, "%s\n", s ); fprintf( stderr, "usage: findr -c -nfet -pfet [rawfile]\n" ); fprintf( stderr, "\tcap -> loading capacitance (in fF)\n" ); fprintf( stderr, "\tw,l -> width, length of fet (in um)\n" ); fprintf( stderr, "\trawfile -> spice rawfile (ascii)\n" ); exit( 1 ); } #define eqsubstr( VS, FS ) ( strncmp( (VS), FS, sizeof( FS ) -1 ) == 0 ) int read_header( f ) FILE *f; { char line[512]; int plotname = 0; char *s; while( fgets( line, 512, f ) ) { if( eqsubstr( line, "Title:" ) ) ; else if( eqsubstr( line, "Date:" ) ) ; else if( eqsubstr( line, "Plotname:" ) ) plotname = 1; else if( eqsubstr( line, "Flags:" ) ) ; else if( eqsubstr( line, "Command:" ) ) ; else if( eqsubstr( line, "No. Variables:" ) ) { if( plotname == 0 ) { fprintf( stderr, "missing Plotname entry\n" ); return( 0 ); } for( s = line; *s != ':'; s++ ); s++; if( sscanf( s, "%d", &plot.nv ) != 1 || plot.nv <= 0 ) { fprintf( stderr, "bad line: %s", line ); return( 0 ); } } else if( eqsubstr( line, "No. Points:" ) ) { if( plotname == 0 ) { fprintf( stderr, "missing Plotname entry\n" ); return( 0 ); } for( s = line; *s != ':'; s++ ); s++; if( sscanf( s, "%d", &plot.np ) != 1 || plot.np <= 0 ) { fprintf( stderr, "bad line: %s", line ); return( 0 ); } } else if( eqsubstr( line, "Variables:" ) ) { if( plotname == 0 || plot.np == 0 | plot.nv == 0 ) { fprintf( stderr, "missing entries:%s%s%s\n", (plotname) ? "" : " 'Plotname'", (plot.nv) ? "" : " 'No. Variables'", (plot.np) ? "" : " 'No. Points'" ); } return( 1 ); } else { fprintf( stderr, "Unrecognized line: %s", line ); return( 0 ); } } fprintf( stderr, "premature EOF\n" ); return( 0 ); } int read_variables( f ) FILE *f; { char line[200], name[100], type[100]; int i; int ix; double *v; char *s, *p; plot.sigs = (Signal *) calloc( plot.nv, sizeof( Signal ) ); if( plot.sigs == NULL ) { fprintf( stderr, "no memory\n" ); return( 0 ); } for( i = 0; i < plot.nv; i++ ) { if( fgets( line, 200, f ) == NULL ) { fprintf( stderr, "premature EOF\n" ); return( 0 ); } if( sscanf( line, "%d %s %s", &ix, name, type ) != 3 ) { fprintf( stderr, "bad 'variable' line: %s", line ); return( 0 ); } s = (char *) malloc( strlen( name ) + 1 ); v = (double *) calloc( plot.np, sizeof( double ) ); if( v == NULL || s == NULL ) { fprintf( stderr, "no memory\n" ); return( 0 ); } plot.sigs[i].vals = v; plot.sigs[i].name = s; for( p = name; *p != '\0'; p++, s++ ) *s = ( isupper( *p ) ) ? tolower( *p ) : *p; *s = '\0'; } if( fgets( line, 100, f ) == NULL ) { fprintf( stderr, "premature EOF\n" ); return( 0 ); } if( eqsubstr( line, "Values:" ) ) return( 1 ); fprintf( stderr, "No 'Values' line\n" ); return( 0 ); } int read_values( f ) FILE *f; { char line[200]; int n, i, n_p, z; double v; for( n = 0; n < plot.np; n++ ) { if( fgets( line, 200, f ) == NULL ) { fprintf( stderr, "premature EOF\n" ); return( 0 ); } if( sscanf( line, "%d%lf", &n_p, &v ) != 2 || n_p != n ) { fprintf( stderr, "bad 'value' line: %s", line ); return( 0 ); } plot.sigs[0].vals[n] = v; for( i = 1; i < plot.nv; i++ ) { if( fgets( line, 200, f ) == NULL ) { fprintf( stderr, "premature EOF\n" ); return( 0 ); } if( sscanf( line, "%lf", &v ) != 1 ) { fprintf( stderr, "bad 'value' line: %s", v, line ); return( 0 ); } plot.sigs[i].vals[n] = v; } } return( 1 ); } Signal *find( name ) char *name; { int i; Signal *sig; for( i = 0, sig = plot.sigs; i < plot.nv; i++, sig++ ) { if( strcmp( name, sig->name ) == 0 ) return( sig ); } return( NULL ); } double interp( y, v1, v2, t1, t2 ) double y, v1, v2, t1, t2; { return( t2 + (y - v2) * (t2 - t1) / (v2 - v1) ); } #define L_H 1 #define H_L 2 #define BOTH ( L_H | H_L ) Signal *FindTransitions( name, which ) char *name; int which; { Signal *sig; double *v, *t; int i; if( (sig = find( name )) == NULL ) { fprintf( stderr, "signal '%s' missing\n" ); return( NULL ); } v = sig->vals; t = timev->vals; if( which & L_H ) { for( i = 1; i < plot.np; i++ ) { if( v[i-1] < midpoint && v[i] >= midpoint ) goto foundlh; } fprintf( stderr, "signal '%s' has no l->h transition\n", name ); return( NULL ); foundlh : sig->lh_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] ); } if( which & H_L ) { for( i = 1; i < plot.np; i++ ) { if( v[i-1] > midpoint && v[i] <= midpoint ) goto foundhl; } fprintf( stderr, "signal '%s' has no h->l transition\n", name ); return( NULL ); foundhl : sig->hl_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] ); } return( sig ); } int find_delays() { Signal *vdd; if( (timev = find( "time" )) == NULL ) { fprintf( stderr, "variable 'time' missing\n" ); return( 0 ); } if( (vdd = find( "vdd" )) == NULL ) { fprintf( stderr, "variable 'vdd' missing\n" ); return( 0 ); } midpoint = vdd->vals[0] / 2.0; if( (in1 = FindTransitions( "in1", BOTH )) == NULL ) return( 0 ); if( (in2 = FindTransitions( "in2", L_H )) == NULL ) return( 0 ); if( (in3 = FindTransitions( "in3", H_L )) == NULL ) return( 0 ); if( (out1 = FindTransitions( "out1", BOTH )) == NULL ) return( 0 ); if( (out2 = FindTransitions( "out2", BOTH )) == NULL ) return( 0 ); if( (out3 = FindTransitions( "out3", L_H )) == NULL ) return( 0 ); if( (out4 = FindTransitions( "out4", H_L )) == NULL ) return( 0 ); out1->tphl = out1->hl_t - in1->lh_t; out1->tplh = out1->lh_t - in1->hl_t; out2->tphl = out2->hl_t - out1->lh_t; out2->tplh = out2->lh_t - out1->hl_t; out3->tplh = out3->lh_t - in2->lh_t; out4->tphl = out4->hl_t - in3->hl_t; return( 1 ); } #define SQ( A ) ( (A) * (A) ) PrintResistEntries( cap, ns, ps ) double cap; TranSz *ns, *ps; { double dyn_h, dyn_l, stat; dyn_h = out3->tplh / cap; dyn_l = out1->tphl / cap; stat = ( SQ( out2->tphl ) - SQ( out1->tphl ) ) / (out1->tplh * cap ); PrintR( "n-channel", ns->w, ns->l, dyn_h, dyn_l, stat ); printf( "\n" ); dyn_h = out1->tplh / cap; dyn_l = out4->tphl / cap; stat = ( SQ( out2->tplh ) - SQ( out1->tplh ) ) / (out1->tphl * cap ); PrintR( "p-channel", ps->w, ps->l, dyn_h, dyn_l, stat ); } #define round( A ) (int) ( (A) + 0.5 ) PrintR( ttype, w, l, rh, rl, rs ) char *ttype; double w, l, rh, rl, rs; { static char *fmt = "resistance %s %s\t%.1f\t%.1f\t%d.0\n"; printf( fmt, ttype, "dynamic-high", w, l, round( rh ) ); printf( fmt, ttype, "dynamic-low\t", w, l, round( rl ) ); printf( fmt, ttype, "static\t", w, l, round( rs ) ); }