2 * sp2sp - test program for spicestream library and
3 * rudimentary spicefile format converter.
5 * Copyright (C) 1998,1999 Stephen G. Tell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include "spicestream.h"
32 #define SWEEP_PREPEND 1
36 int sweep_mode
= SWEEP_PREPEND
;
37 char *progname
= "sp2sp";
39 static void ascii_header_output(SpiceStream
*sf
, int *enab
, int nidx
);
40 static void ascii_data_output(SpiceStream
*sf
, int *enab
, int nidx
,
41 double begin_val
, double end_val
, int ndigits
);
42 static int parse_field_numbers(int **index
, int *idxsize
, int *nsel
,
43 char *list
, int nfields
);
44 static int parse_field_names(int **index
, int *idxsize
, int *nsel
,
45 char *list
, SpiceStream
*sf
);
46 static VarType
get_vartype_code(char *vartype
);
53 fprintf(stderr
, "usage: %s [options] file\n", progname
);
54 fprintf(stderr
, " options:\n");
55 fprintf(stderr
, " -b V begin output after independent-variable value V is reached\n");
56 fprintf(stderr
, " instead of start of input\n");
57 fprintf(stderr
, " -c T Convert output to type T\n");
58 fprintf(stderr
, " -d N use N significant digits in output\n");
59 fprintf(stderr
, " -e V stop after independent-variable value V is reached\n");
60 fprintf(stderr
, " instead of end of input.\n");
62 fprintf(stderr
, " -f f1,f2,... Output only fields named f1, f2, etc.\n");
63 fprintf(stderr
, " -n n1,n2,... Output only fields n1, n2, etc;\n");
64 fprintf(stderr
, " independent variable is field number 0\n");
65 fprintf(stderr
, " -u U Output only variables with units of type; U\n");
66 fprintf(stderr
, " U = volts, amps, etc.\n");
67 fprintf(stderr
, " -s S Handle sweep parameters as S:\n");
68 fprintf(stderr
, " -s head add header-like comment line\n");
69 fprintf(stderr
, " -s prepend prepend columns to all output lines\n");
70 fprintf(stderr
, " -s none ignore sweep info\n");
71 fprintf(stderr
, " -t T Assume that input is of type T\n");
72 fprintf(stderr
, " -v Verbose - print detailed signal information\n");
73 fprintf(stderr
, " output format types:\n");
74 fprintf(stderr
, " none - no data output\n");
75 fprintf(stderr
, " ascii - lines of space-seperated numbers, with header\n");
76 fprintf(stderr
, " nohead - lines of space-seperated numbers, no headers\n");
77 fprintf(stderr
, " cazm - CAzM format\n");
78 fprintf(stderr
, " input format types:\n");
81 while(s
= ss_filetype_name(i
++)) {
82 fprintf(stderr
, " %s\n", s
);
87 main(int argc
, char **argv
)
97 char *infiletype
= "hspice";
98 char *outfiletype
= "ascii";
99 char *fieldnamelist
= NULL
;
100 char *fieldnumlist
= NULL
;
101 int *out_indices
= NULL
;
104 VarType vartype
= UNKNOWN
;
107 double begin_val
= -DBL_MAX
;
108 double end_val
= DBL_MAX
;
110 while ((c
= getopt (argc
, argv
, "b:c:d:e:f:n:s:t:u:vx")) != EOF
) {
113 spicestream_msg_level
= DBG
;
117 begin_val
= atof(optarg
);
120 outfiletype
= optarg
;
123 ndigits
= atoi(optarg
);
128 end_val
= atof(optarg
);
131 fieldnamelist
= optarg
;
134 fieldnumlist
= optarg
;
137 if(strcmp(optarg
, "none") == 0)
138 sweep_mode
= SWEEP_NONE
;
139 else if(strcmp(optarg
, "prepend") == 0)
140 sweep_mode
= SWEEP_PREPEND
;
141 else if(strcmp(optarg
, "head") == 0)
142 sweep_mode
= SWEEP_HEAD
;
144 fprintf(stderr
, "unknown sweep-data style %s\n", optarg
);
152 vartype
= get_vartype_code(optarg
);
155 spicestream_msg_level
= DBG
;
164 if(errflg
|| optind
>= argc
) {
169 sf
= ss_open(argv
[optind
], infiletype
);
172 perror(argv
[optind
]);
173 fprintf(stderr
, "unable to read file\n");
177 printf("filename: \"%s\"\n", sf
->filename
);
178 printf(" columns: %d\n", sf
->ncols
);
179 printf(" tables: %d\n", sf
->ntables
);
180 printf("independent variable:\n");
181 printf(" name: \"%s\"\n", sf
->ivar
->name
);
182 printf(" type: %s\n", vartype_name_str(sf
->ivar
->type
));
183 printf(" col: %d\n", sf
->ivar
->col
);
184 printf(" ncols: %d\n", sf
->ivar
->ncols
);
185 printf("sweep parameters: %d\n", sf
->nsweepparam
);
186 for(i
= 0; i
< sf
->nsweepparam
; i
++) {
187 printf(" name: \"%s\"\n", sf
->spar
[i
].name
);
188 printf(" type: %s\n", vartype_name_str(sf
->spar
[i
].type
));
190 printf("dependent variables: %d\n", sf
->ndv
);
191 for(i
= 0; i
< sf
->ndv
; i
++) {
192 printf(" dv[%d] \"%s\" ", i
, sf
->dvar
[i
].name
);
193 printf(" (type=%s col=%d ncols=%d)\n",
194 vartype_name_str(sf
->dvar
[i
].type
),
200 if(fieldnamelist
== NULL
&& fieldnumlist
== NULL
) {
201 out_indices
= g_new0(int, sf
->ndv
+1);
204 for(i
= 0; i
< sf
->ndv
+1; i
++) {
207 || sf
->dvar
[i
-1].type
== vartype
)) {
208 out_indices
[idx
++] = i
;
214 if(parse_field_numbers(&out_indices
, &outi_size
, &nsel
,
215 fieldnumlist
, sf
->ndv
+1) < 0)
218 if(parse_field_names(&out_indices
, &outi_size
, &nsel
,
219 fieldnamelist
, sf
) < 0)
222 fprintf(stderr
, "No fields selected for output\n");
226 if(strcmp(outfiletype
, "cazm") == 0) {
227 printf("* CAZM-format output converted with sp2sp\n");
229 printf("TRANSIENT ANALYSIS\n");
230 ascii_header_output(sf
, out_indices
, nsel
);
231 ascii_data_output(sf
, out_indices
, nsel
, begin_val
, end_val
, ndigits
);
232 } else if(strcmp(outfiletype
, "ascii") == 0) {
233 ascii_header_output(sf
, out_indices
, nsel
);
234 ascii_data_output(sf
, out_indices
, nsel
, begin_val
, end_val
, ndigits
);
235 } else if(strcmp(outfiletype
, "nohead") == 0) {
236 ascii_data_output(sf
, out_indices
, nsel
, begin_val
, end_val
, ndigits
);
237 } else if(strcmp(outfiletype
, "none") == 0) {
240 fprintf(stderr
, "%s: invalid output type name: %s\n",
241 progname
, outfiletype
);
250 * print all column headers.
251 * For multicolumn variables, ss_var_name will generate a column name
252 * consisting of the variable name plus a suffix.
255 ascii_header_output(SpiceStream
*sf
, int *indices
, int nidx
)
260 if((sf
->nsweepparam
> 0) && (sweep_mode
== SWEEP_PREPEND
)) {
261 for(i
= 0; i
< sf
->nsweepparam
; i
++) {
262 printf("%s ", sf
->spar
[i
].name
);
265 for(i
= 0; i
< nidx
; i
++) {
268 if(indices
[i
] == 0) {
269 ss_var_name(sf
->ivar
, 0, buf
, 1024);
272 int varno
= indices
[i
]-1;
273 for(j
= 0; j
< sf
->dvar
[varno
].ncols
; j
++) {
276 ss_var_name(&sf
->dvar
[varno
], j
, buf
, 1024);
285 * print data as space-seperated columns.
288 ascii_data_output(SpiceStream
*sf
, int *indices
, int nidx
,
289 double begin_val
, double end_val
, int ndigits
)
298 dvals
= g_new(double, sf
->ncols
);
299 if(sf
->nsweepparam
> 0)
300 spar
= g_new(double, sf
->nsweepparam
);
305 if(sf
->nsweepparam
> 0) {
306 if(ss_readsweep(sf
, spar
) <= 0)
309 if(tab
> 0 && sweep_mode
== SWEEP_HEAD
) {
310 printf("# sweep %d;", tab
);
311 for(i
= 0; i
< sf
->nsweepparam
; i
++) {
312 printf(" %s=%g", sf
->spar
[i
].name
, spar
[i
]);
316 while((rc
= ss_readrow(sf
, &ival
, dvals
)) > 0) {
320 /* past end_val, but can only stop reading
321 early if if there is only one sweep-table
329 if((sf
->nsweepparam
> 0) && (sweep_mode
== SWEEP_PREPEND
)) {
330 for(i
= 0; i
< sf
->nsweepparam
; i
++) {
331 printf("%.*g ", ndigits
, spar
[i
]);
334 for(i
= 0; i
< nidx
; i
++) {
338 printf("%.*g", ndigits
, ival
);
340 int varno
= indices
[i
]-1;
341 int dcolno
= sf
->dvar
[varno
].col
- 1;
342 for(j
= 0; j
< sf
->dvar
[varno
].ncols
; j
++) {
345 printf("%.*g", ndigits
,
352 if(rc
== -2) { /* end of sweep, more follow */
353 if(sf
->nsweepparam
== 0)
354 sweep_mode
= SWEEP_HEAD
;
356 } else { /* EOF or error */
365 static int parse_field_numbers(int **indices
, int *idxsize
, int *nidx
,
366 char *list
, int nfields
)
372 if(!*indices
|| idxsize
== 0) {
373 *idxsize
= nfields
*2;
374 idx
= g_new0(int, *idxsize
);
379 fnum
= strtok(list
, ", \t");
382 if(*nidx
>= *idxsize
) {
384 idx
= g_realloc(idx
, (*idxsize
) * sizeof(int));
388 if(n
< 0 || n
>= nfields
) {
389 fprintf(stderr
, "bad field number in -n option: %s\n", fnum
);
395 fnum
= strtok(NULL
, ", \t");
402 * Try looking for named dependent variable. Try twice,
403 * first as-is, then with "v(" prepended the way hspice mangles things.
405 static int find_dv_by_name(char *name
, SpiceStream
*sf
)
408 for(i
= 0; i
< sf
->ndv
; i
++) {
409 if(strcasecmp(name
, sf
->dvar
[i
].name
) == 0)
412 for(i
= 0; i
< sf
->ndv
; i
++) {
413 if(strncasecmp("v(", sf
->dvar
[i
].name
, 2) == 0
414 && strcasecmp(name
, &sf
->dvar
[i
].name
[2]) == 0)
421 * parse comma-seperated list of field names. Turn on the output-enables
422 * for the listed fields.
424 static int parse_field_names(int **indices
, int *idxsize
, int *nidx
,
425 char *list
, SpiceStream
*sf
)
433 if(!*indices
|| idxsize
== 0) {
434 *idxsize
= (sf
->ndv
+1)*2;
435 idx
= g_new0(int, *idxsize
);
440 fld
= strtok(list
, ", \t");
443 if(*nidx
>= *idxsize
) {
445 idx
= g_realloc(idx
, (*idxsize
) * sizeof(int));
448 if(strcasecmp(fld
, sf
->ivar
->name
)==0) {
451 } else if((n
= find_dv_by_name(fld
, sf
)) >= 0) {
455 fprintf(stderr
, "field name in -f option not found in file: %s\n", fld
);
458 fld
= strtok(NULL
, ", \t");
468 static struct vtlistel vtlist
[] = {
472 {VOLTAGE
, "voltage"},
473 {CURRENT
, "current"},
476 {FREQUENCY
, "frequency"},
477 {FREQUENCY
, "hertz"},
482 * Given a variable type name, return a numeric VarType.
483 * Returns 0 (UNKNOWN) if no match.
485 static VarType
get_vartype_code(char *vartype
)
488 for(i
= 0; vtlist
[i
].s
; i
++) {
489 if(strcasecmp(vartype
, vtlist
[i
].s
) == 0)