1 #include <stdio.h>
2 #include <ctype.h>
3 #include <malloc.h>
4 #include <string.h>
5 #include <stdlib.h>
6 
7 
8 typedef struct
9   {
10     char    *name;
11     double  *vals;
12     double  hl_t;
13     double  lh_t;
14     double  tphl;
15     double  tplh;
16   } Signal;
17 
18 
19 struct
20   {
21     int     nv;
22     int     np;
23     Signal  *sigs;
24   } plot;
25 
26 typedef struct
27   {
28     double  w, l;
29   } TranSz;
30 
31 
32 double midpoint;
33 
34 Signal *timev, *in1, *in2, *in3, *out1, *out2, *out3, *out4;
35 
36 
main(argc,argv)37 main( argc, argv )
38   int   argc;
39   char  *argv[];
40   {
41     FILE    *fi = stdin;
42     TranSz  p, n;
43     double  cap;
44     int     i;
45 
46     cap = p.w = p.l = n.w = n.l = -1;
47     for( i = 1; i < argc; i++ )
48       {
49 	if( argv[i][0] == '-' )
50 	  {
51 	    switch( argv[i][1] )
52 	      {
53 		case 'c' :
54 		    i++;
55 		    if( i >= argc ) usage( "missing argument :" );
56 		    if( sscanf( argv[i], "%lf", &cap ) != 1 || cap <= 0 )
57 			usage( "bad argument for 'c': " );
58 		    cap *= 1E-15;	/* convert to ff */
59 		    break;
60 		case 'n' :
61 		    i++;
62 		    if( i >= argc ) usage( "missing argument :" );
63 		    if( sscanf( argv[i], "%lf,%lf", &n.w, &n.l ) != 2 ||
64 		      n.w <= 0 || n.l <= 0 )
65 			usage( "bad argument for 'n': " );
66 		    break;
67 		case 'p' :
68 		    i++;
69 		    if( i >= argc ) usage( "missing argument :" );
70 		    if( sscanf( argv[i], "%lf,%lf", &p.w, &p.l ) != 2 ||
71 		      p.w <= 0 || p.l <= 0 )
72 			usage( "bad argument for 'p': " );
73 		    break;
74 		default :
75 		    usage( "unknown switch :" );
76 	      }
77 	  }
78 	else
79 	  {
80 	    if( (fi = fopen( argv[i], "r" )) == NULL )
81 		usage( "can not open input file :" );
82 	  }
83       }
84 
85     if( cap <= 0 || n.l <= 0 || n.w <= 0 || p.l <= 0 || p.w <= 0 )
86 	usage( "i am missing parameters:" );
87 
88     if( read_header( fi ) == 0 )
89 	exit( 1 );
90     if( read_variables( fi ) == 0 )
91 	exit( 1 );
92     if( read_values( fi ) == 0 )
93 	exit( 1 );
94     if( find_delays() == 0 )
95 	exit( 1 );
96 
97     PrintResistEntries( cap, &n, &p );
98     exit( 0 );
99   }
100 
101 
usage(s)102 usage( s )
103   char *s;
104   {
105     fprintf( stderr, "%s\n", s );
106     fprintf( stderr, "usage: findr -c <cap> -nfet <w,l> -pfet <w,l> [rawfile]\n" );
107     fprintf( stderr, "\tcap     -> loading capacitance (in fF)\n" );
108     fprintf( stderr, "\tw,l     -> width, length of fet (in um)\n" );
109     fprintf( stderr, "\trawfile -> spice rawfile (ascii)\n" );
110     exit( 1 );
111   }
112 
113 
114 #define eqsubstr( VS, FS )	( strncmp( (VS), FS, sizeof( FS ) -1 ) == 0 )
115 
read_header(f)116 int read_header( f )
117   FILE  *f;
118   {
119     char  line[512];
120     int   plotname = 0;
121     char  *s;
122 
123     while( fgets( line, 512, f ) )
124       {
125 	if( eqsubstr( line, "Title:" ) )
126 	    ;
127 	else if( eqsubstr( line, "Date:" ) )
128 	    ;
129 	else if( eqsubstr( line, "Plotname:" ) )
130 	    plotname = 1;
131 	else if( eqsubstr( line, "Flags:" ) )
132 	    ;
133 	else if( eqsubstr( line, "Command:" ) )
134 	    ;
135 	else if( eqsubstr( line, "No. Variables:" ) )
136 	  {
137 	    if( plotname == 0 )
138 	      {
139 		fprintf( stderr, "missing Plotname entry\n" );
140 		return( 0 );
141 	      }
142 	    for( s = line; *s != ':'; s++ );
143 	    s++;
144 	    if( sscanf( s, "%d", &plot.nv ) != 1 || plot.nv <= 0 )
145 	      {
146 		fprintf( stderr, "bad line: %s", line );
147 		return( 0 );
148 	      }
149 	  }
150 	else if( eqsubstr( line, "No. Points:" ) )
151 	  {
152 	    if( plotname == 0 )
153 	      {
154 		fprintf( stderr, "missing Plotname entry\n" );
155 		return( 0 );
156 	      }
157 	    for( s = line; *s != ':'; s++ );
158 	    s++;
159 	    if( sscanf( s, "%d", &plot.np ) != 1 || plot.np <= 0 )
160 	      {
161 		fprintf( stderr, "bad line: %s", line );
162 		return( 0 );
163 	      }
164 	  }
165 	else if( eqsubstr( line, "Variables:" ) )
166 	  {
167 	    if( plotname == 0 || plot.np == 0 | plot.nv == 0 )
168 	      {
169 		fprintf( stderr, "missing entries:%s%s%s\n",
170 		  (plotname) ? "" : " 'Plotname'",
171 		  (plot.nv) ? "" : " 'No. Variables'",
172 		  (plot.np) ? "" : " 'No. Points'" );
173 	      }
174 	    return( 1 );
175 	  }
176 	else
177 	  {
178 	    fprintf( stderr, "Unrecognized line: %s", line );
179 	    return( 0 );
180 	  }
181       }
182     fprintf( stderr, "premature EOF\n" );
183     return( 0 );
184   }
185 
186 
187 
read_variables(f)188 int read_variables( f )
189   FILE  *f;
190   {
191     char    line[200], name[100], type[100];
192     int     i;
193     int     ix;
194     double  *v;
195     char    *s, *p;
196 
197     plot.sigs = (Signal *) calloc( plot.nv, sizeof( Signal ) );
198     if( plot.sigs == NULL )
199       {
200 	fprintf( stderr, "no memory\n" );
201 	return( 0 );
202       }
203 
204     for( i = 0; i < plot.nv; i++ )
205       {
206 	if( fgets( line, 200, f ) == NULL )
207 	  {
208 	    fprintf( stderr, "premature EOF\n" );
209 	    return( 0 );
210 	  }
211 	if( sscanf( line, "%d %s %s", &ix, name, type ) != 3 )
212 	  {
213 	    fprintf( stderr, "bad 'variable' line: %s", line );
214 	    return( 0 );
215 	  }
216 	s = (char *) malloc( strlen( name ) + 1 );
217 	v = (double *) calloc( plot.np, sizeof( double ) );
218 	if( v == NULL || s == NULL )
219 	  {
220 	    fprintf( stderr, "no memory\n" );
221 	    return( 0 );
222 	  }
223 	plot.sigs[i].vals = v;
224 	plot.sigs[i].name = s;
225 	for( p = name; *p != '\0'; p++, s++ )
226 	    *s = ( isupper( *p ) ) ? tolower( *p ) : *p;
227 	*s = '\0';
228       }
229 
230     if( fgets( line, 100, f ) == NULL )
231       {
232 	fprintf( stderr, "premature EOF\n" );
233 	return( 0 );
234       }
235     if( eqsubstr( line, "Values:" ) )
236 	return( 1 );
237 
238     fprintf( stderr, "No 'Values' line\n" );
239     return( 0 );
240   }
241 
242 
read_values(f)243 int read_values( f )
244   FILE  *f;
245   {
246     char    line[200];
247     int     n, i, n_p, z;
248     double  v;
249 
250     for( n = 0; n < plot.np; n++ )
251       {
252 	if( fgets( line, 200, f ) == NULL )
253 	  {
254 	    fprintf( stderr, "premature EOF\n" );
255 	    return( 0 );
256 	  }
257 
258 	if( sscanf( line, "%d%lf", &n_p, &v ) != 2 || n_p != n )
259 	  {
260 	    fprintf( stderr, "bad 'value' line: %s", line );
261 	    return( 0 );
262 	  }
263 
264 	plot.sigs[0].vals[n] = v;
265 	for( i = 1; i < plot.nv; i++ )
266 	  {
267 	    if( fgets( line, 200, f ) == NULL )
268 	      {
269 		fprintf( stderr, "premature EOF\n" );
270 		return( 0 );
271 	      }
272 	    if( sscanf( line, "%lf", &v ) != 1 )
273 	      {
274 		fprintf( stderr, "bad 'value' line: %s", v, line );
275 		return( 0 );
276 	      }
277 	    plot.sigs[i].vals[n] = v;
278 	  }
279       }
280     return( 1 );
281   }
282 
283 
find(name)284 Signal *find( name )
285   char  *name;
286   {
287     int     i;
288     Signal  *sig;
289 
290     for( i = 0, sig = plot.sigs; i < plot.nv; i++, sig++ )
291       {
292 	if( strcmp( name, sig->name ) == 0 )
293 	    return( sig );
294       }
295     return( NULL );
296   }
297 
298 
interp(y,v1,v2,t1,t2)299 double interp( y, v1, v2, t1, t2 )
300   double y, v1, v2, t1, t2;
301   {
302     return( t2 + (y - v2) * (t2 - t1) / (v2 - v1) );
303   }
304 
305 
306 #define	L_H	1
307 #define	H_L	2
308 #define BOTH	( L_H | H_L )
309 
FindTransitions(name,which)310 Signal *FindTransitions( name, which )
311   char  *name;
312   int   which;
313   {
314     Signal  *sig;
315     double  *v, *t;
316     int     i;
317 
318     if( (sig = find( name )) == NULL )
319       {
320 	fprintf( stderr, "signal '%s' missing\n" );
321 	return( NULL );
322       }
323     v = sig->vals;
324     t = timev->vals;
325 
326     if( which & L_H )
327       {
328 	for( i = 1; i < plot.np; i++ )
329 	  {
330 	    if( v[i-1] < midpoint && v[i] >= midpoint )
331 		goto foundlh;
332 	  }
333 	fprintf( stderr, "signal '%s' has no l->h transition\n", name );
334 	return( NULL );
335 
336       foundlh :
337 	sig->lh_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] );
338       }
339 
340     if( which & H_L )
341       {
342 	for( i = 1; i < plot.np; i++ )
343 	  {
344 	    if( v[i-1] > midpoint && v[i] <= midpoint )
345 		goto foundhl;
346 	  }
347 	fprintf( stderr, "signal '%s' has no h->l transition\n", name );
348 	return( NULL );
349 
350       foundhl :
351 	sig->hl_t = interp( midpoint, v[i-1], v[i], t[i-1], t[i] );
352       }
353 
354     return( sig );
355   }
356 
357 
find_delays()358 int find_delays()
359   {
360     Signal  *vdd;
361 
362     if( (timev = find( "time" )) == NULL )
363       {
364 	fprintf( stderr, "variable 'time' missing\n" );
365 	return( 0 );
366       }
367     if( (vdd = find( "v(vdd)" )) == NULL )
368       {
369 	fprintf( stderr, "variable 'vdd' missing\n" );
370 	return( 0 );
371       }
372     midpoint = vdd->vals[0] / 2.0;
373 
374     if( (in1 = FindTransitions( "v(in1)", BOTH )) == NULL ) return( 0 );
375     if( (in2 = FindTransitions( "v(in2)", L_H )) == NULL ) return( 0 );
376     if( (in3 = FindTransitions( "v(in3)", H_L )) == NULL ) return( 0 );
377     if( (out1 = FindTransitions( "v(out1)", BOTH )) == NULL ) return( 0 );
378     if( (out2 = FindTransitions( "v(out2)", BOTH )) == NULL ) return( 0 );
379     if( (out3 = FindTransitions( "v(out3)", L_H )) == NULL ) return( 0 );
380     if( (out4 = FindTransitions( "v(out4)", H_L )) == NULL ) return( 0 );
381 
382     out1->tphl = out1->hl_t - in1->lh_t;
383     out1->tplh = out1->lh_t - in1->hl_t;
384 
385     out2->tphl = out2->hl_t - out1->lh_t;
386     out2->tplh = out2->lh_t - out1->hl_t;
387 
388     out3->tplh = out3->lh_t - in2->lh_t;
389     out4->tphl = out4->hl_t - in3->hl_t;
390 
391     return( 1 );
392   }
393 
394 
395 #define	SQ( A )		( (A) * (A) )
396 
PrintResistEntries(cap,ns,ps)397 PrintResistEntries( cap, ns, ps )
398   double  cap;
399   TranSz  *ns, *ps;
400   {
401     double  dyn_h, dyn_l, stat;
402 
403     dyn_h = out3->tplh / cap;
404     dyn_l = out1->tphl / cap;
405     stat = ( SQ( out2->tphl ) - SQ( out1->tphl ) ) / (out1->tplh * cap );
406     PrintR( "n-channel", ns->w, ns->l, dyn_h, dyn_l, stat );
407 
408     printf( "\n" );
409 
410     dyn_h = out1->tplh / cap;
411     dyn_l = out4->tphl / cap;
412     stat = ( SQ( out2->tplh ) - SQ( out1->tplh ) ) / (out1->tphl * cap );
413     PrintR( "p-channel", ps->w, ps->l, dyn_h, dyn_l, stat );
414   }
415 
416 
417 #define	round( A )	(int) ( (A) + 0.5 )
418 
419 
PrintR(ttype,w,l,rh,rl,rs)420 PrintR( ttype, w, l, rh, rl, rs )
421   char    *ttype;
422   double  w, l, rh, rl, rs;
423   {
424     static char *fmt = "resistance %s %s\t%.1f\t%.1f\t%d.0\n";
425 
426     printf( fmt, ttype, "dynamic-high", w, l, round( rh ) );
427     printf( fmt, ttype, "dynamic-low\t", w, l, round( rl ) );
428     printf( fmt, ttype, "static\t", w, l, round( rs ) );
429   }
430