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