1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: io.c
6 * Input/output tool: controller module
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 #include "global.h"
33 #include "database.h"
34 #include "conlay.h"
35 #include "egraphics.h"
36 #include "efunction.h"
37 #include "dbcontour.h"
38 #include "eio.h"
39 #include "usr.h"
40 #include "drc.h"
41 #include "network.h"
42 #include "usredtec.h"
43 #include "edialogs.h"
44 #include "tecart.h"
45 #include "tecschem.h"
46 #include "tecgen.h"
47 #include "tecmocmos.h"
48 #include <math.h>
49
50 /* the command parsing table */
51 static KEYWORD iocifoopt[] =
52 {
53 {x_("fully-instantiated"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
54 {x_("exactly-as-displayed"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
55 {x_("individual-boxes"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
56 {x_("merge-boxes"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
57 {x_("include-cloak-layer"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
58 {x_("ignore-cloak-layer"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
59 {x_("normalized"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
60 {x_("not-normalized"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
61 {x_("exactly-as-displayed"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
62 {x_("instantiate-top"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
63 {x_("dont-instantiate-top"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
64 {x_("highlight-resolution"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
65 {x_("hide-resolution"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
66 TERMKEY
67 };
68 COMCOMP io_cifop = {iocifoopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
69 INPUTOPT, x_(" \t"), M_("style of CIF output"), 0};
70 static KEYWORD iocifiopt[] =
71 {
72 {x_("rounded-wires"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
73 {x_("squared-wires"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
74 TERMKEY
75 };
76 static COMCOMP iocifip = {iocifiopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
77 INPUTOPT, x_(" \t"), M_("style of CIF input"), 0};
78 static KEYWORD iocifopt[] =
79 {
80 {x_("input"), 1,{&iocifip,NOKEY,NOKEY,NOKEY,NOKEY}},
81 {x_("output"), 1,{&io_cifop,NOKEY,NOKEY,NOKEY,NOKEY}},
82 TERMKEY
83 };
84 COMCOMP io_cifp = {iocifopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
85 INPUTOPT, x_(" \t"), M_("control of CIF"), 0};
86
87 static KEYWORD iodxfaopt[] =
88 {
89 {x_("all"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
90 {x_("restrict"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
91 TERMKEY
92 };
93 static COMCOMP iodxfap = {iodxfaopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
94 INPUTOPT, x_(" \t"), M_("DXF layer restriction options"), 0};
95 static KEYWORD iodxfopt[] =
96 {
97 {x_("acceptable-layers"), 1,{&iodxfap,NOKEY,NOKEY,NOKEY,NOKEY}},
98 {x_("flatten-input"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
99 {x_("not-flatten-input"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
100 TERMKEY
101 };
102 COMCOMP io_dxfp = {iodxfopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
103 INPUTOPT, x_(" \t"), M_("DXF options"), 0};
104
105 static COMCOMP iogdsoarp = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
106 INPUTOPT, x_(" \t"), M_("maximum number of degrees per arc segment"), 0};
107 static COMCOMP iogdsoasp = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
108 INPUTOPT, x_(" \t"), M_("maximum sag distance for an arc segment"), 0};
109 static KEYWORD iogdsoopt[] =
110 {
111 {x_("individual-boxes"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
112 {x_("merge-boxes"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
113 {x_("include-cloak-layer"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
114 {x_("ignore-cloak-layer"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
115 {x_("arc-resolution"), 1,{&iogdsoarp,NOKEY,NOKEY,NOKEY,NOKEY}},
116 {x_("arc-sag"), 1,{&iogdsoasp,NOKEY,NOKEY,NOKEY,NOKEY}},
117 TERMKEY
118 };
119 static COMCOMP iogdsop = {iogdsoopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
120 INPUTOPT, x_(" \t"), M_("style of GDS output"), 0};
121 static KEYWORD iogdsiopt[] =
122 {
123 {x_("text"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
124 {x_("expand"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
125 {x_("arrays"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
126 {x_("unknown-layers"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
127 {x_("no-text"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
128 {x_("no-expand"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
129 {x_("no-arrays"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
130 {x_("no-unknown-layers"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
131 TERMKEY
132 };
133 static COMCOMP iogdsiop = {iogdsiopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
134 INPUTOPT, x_(" \t"), M_("style of GDS input"), 0};
135 static KEYWORD iogdsopt[] =
136 {
137 {x_("output"), 1,{&iogdsop,NOKEY,NOKEY,NOKEY,NOKEY}},
138 {x_("input"), 1,{&iogdsiop,NOKEY,NOKEY,NOKEY,NOKEY}},
139 TERMKEY
140 };
141 COMCOMP io_gdsp = {iogdsopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
142 INPUTOPT, x_(" \t"), M_("control of GDS"), 0};
143
144 static KEYWORD ioedifopt[] =
145 {
146 {x_("schematic"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
147 {x_("netlist"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
148 TERMKEY
149 };
150 COMCOMP io_edifp = {ioedifopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
151 INPUTOPT, x_(" \t"), M_("EDIF output option"), 0};
152
153 static KEYWORD ioplotnopt[] =
154 {
155 {x_("focus"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
156 {x_("include-date"),0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
157 TERMKEY
158 };
159 static COMCOMP ioplotnp = {ioplotnopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
160 INPUTOPT, x_(" \t"), M_("negating control of plot output"), 0};
161 static KEYWORD ioplotopt[] =
162 {
163 {x_("not"), 1,{&ioplotnp,NOKEY,NOKEY,NOKEY,NOKEY}},
164 {x_("focus-highlighted"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
165 {x_("focus-window"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
166 {x_("include-date"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
167 TERMKEY
168 };
169 static COMCOMP ioplotp = {ioplotopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
170 INPUTOPT, x_(" \t"), M_("control of plot output"), 0};
171
172 static KEYWORD ioveropt[] =
173 {
174 {x_("off"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
175 {x_("on"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
176 {x_("graphical"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
177 TERMKEY
178 };
179 static COMCOMP ioverp = {ioveropt,NOTOPLIST,NONEXTLIST,NOPARAMS,
180 INPUTOPT, x_(" \t"), M_("verbose option"), 0};
181
182 static COMCOMP iopostsynch = {NOKEYWORD, topoffile, nextfile, NOPARAMS,
183 NOFILL|INPUTOPT, x_(" \t"), M_("PostScript synchronization file name"), 0};
184 static COMCOMP iopostplotwid = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
185 INPUTOPT, x_(" \t"), M_("PostScript plotter width"), 0};
186 static COMCOMP iopostprintwid = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
187 INPUTOPT, x_(" \t"), M_("PostScript printer width"), 0};
188 static COMCOMP iopostprinthei = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
189 INPUTOPT, x_(" \t"), M_("PostScript printer height"), 0};
190 static COMCOMP iopostmargin = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
191 INPUTOPT, x_(" \t"), M_("PostScript margin"), 0};
192 static KEYWORD iopostopt[] =
193 {
194 {x_("plain"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
195 {x_("encapsulated"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
196 {x_("rotate"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
197 {x_("no-rotate"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
198 {x_("auto-rotate"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
199 {x_("color"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
200 {x_("stippled-color"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
201 {x_("merged-color"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
202 {x_("gray-scale"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
203 {x_("printer"), 2,{&iopostprintwid,&iopostprinthei,NOKEY,NOKEY,NOKEY}},
204 {x_("plotter"), 1,{&iopostplotwid,NOKEY,NOKEY,NOKEY,NOKEY}},
205 {x_("margin"), 1,{&iopostmargin,NOKEY,NOKEY,NOKEY,NOKEY}},
206 {x_("unsynchronize"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
207 {x_("synchronize"), 1,{&iopostsynch,NOKEY,NOKEY,NOKEY,NOKEY}},
208 TERMKEY
209 };
210 static COMCOMP iopostp = {iopostopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
211 INPUTOPT, x_(" \t"), M_("control of PostScript format"), 0};
212
213 static COMCOMP iohpgl2sp = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
214 INPUTOPT, x_(" \t"), M_("internal units per pixel"), 0};
215 static KEYWORD iohpgl2opt[] =
216 {
217 {x_("scale"), 1,{&iohpgl2sp,NOKEY,NOKEY,NOKEY,NOKEY}},
218 TERMKEY
219 };
220 static COMCOMP iohpgl2p = {iohpgl2opt,NOTOPLIST,NONEXTLIST,NOPARAMS,
221 INPUTOPT, x_(" \t"), M_("HPGL/2 scaling option"), 0};
222 static KEYWORD iohpglopt[] =
223 {
224 {x_("1"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
225 {x_("2"), 1,{&iohpgl2p,NOKEY,NOKEY,NOKEY,NOKEY}},
226 TERMKEY
227 };
228 static COMCOMP iohpglp = {iohpglopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
229 INPUTOPT, x_(" \t"), M_("HPGL version"), 0};
230
231 static COMCOMP iobloatlp = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
232 INPUTOPT, x_(" \t"), M_("Layer name to bloat"), 0};
233 static COMCOMP iobloatap = {NOKEYWORD,NOTOPLIST,NONEXTLIST,NOPARAMS,
234 0, x_(" \t"), M_("amount to bloat layer (in internal units)"), 0};
235
236 static KEYWORD iobinopt[] =
237 {
238 {x_("no-backup"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
239 {x_("one-level-backup"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
240 {x_("many-level-backup"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
241 {x_("no-check"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
242 {x_("check"), 0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
243 TERMKEY
244 };
245 static COMCOMP iobinp = {iobinopt,NOTOPLIST,NONEXTLIST,NOPARAMS,
246 INPUTOPT, x_(" \t"), M_("Binary options"), 0};
247
248 static KEYWORD ioopt[] =
249 {
250 {x_("cif"), 1,{&io_cifp,NOKEY,NOKEY,NOKEY,NOKEY}},
251 {x_("dxf"), 1,{&io_dxfp,NOKEY,NOKEY,NOKEY,NOKEY}},
252 {x_("gds"), 1,{&io_gdsp,NOKEY,NOKEY,NOKEY,NOKEY}},
253 {x_("edif"), 1,{&io_edifp,NOKEY,NOKEY,NOKEY,NOKEY}},
254 {x_("binary"), 1,{&iobinp,NOKEY,NOKEY,NOKEY,NOKEY}},
255 {x_("plot"), 1,{&ioplotp,NOKEY,NOKEY,NOKEY,NOKEY}},
256 {x_("verbose"), 1,{&ioverp,NOKEY,NOKEY,NOKEY,NOKEY}},
257 {x_("postscript"), 1,{&iopostp,NOKEY,NOKEY,NOKEY,NOKEY}},
258 {x_("hpgl"), 1,{&iohpglp,NOKEY,NOKEY,NOKEY,NOKEY}},
259 {x_("bloat-output"), 2,{&iobloatlp,&iobloatap,NOKEY,NOKEY,NOKEY}},
260 TERMKEY
261 };
262 COMCOMP io_iop = {ioopt, NOTOPLIST, NONEXTLIST, NOPARAMS,
263 0, x_(" \t"), M_("Input/Output action"), 0};
264
265 static struct
266 {
267 CHAR *name;
268 INTBIG required, bits;
269 } io_formatlist[] =
270 {
271 {x_("binary"), 1, FBINARY},
272 {x_("nobackupbinary"), 1, FBINARYNOBACKUP},
273 {x_("cif"), 1, FCIF},
274 {x_("def"), 2, FDEF},
275 {x_("dxf"), 2, FDXF},
276 {x_("eagle"), 2, FEAGLE},
277 {x_("ecad"), 2, FECAD},
278 {x_("edif"), 2, FEDIF},
279 {x_("gds"), 1, FGDS},
280 {x_("hpgl"), 1, FHPGL},
281 {x_("l"), 1, FL},
282 {x_("lef"), 2, FLEF},
283 {x_("pads"), 2, FPADS},
284 {x_("postscript"), 2, FPOSTSCRIPT},
285 {x_("printed-postscript"), 2, FPRINTEDPOSTSCRIPT},
286 #if defined(MACOS) && !defined(MACOSX)
287 {x_("quickdraw"), 1, FQUICKDRAW},
288 #endif
289 {x_("sdf"), 2, FSDF},
290 #ifdef FORCECADENCE
291 {x_("skill"), 2, FSKILL},
292 #endif
293 {x_("sue"), 2, FSUE},
294 {x_("text"), 1, FTEXT},
295 #if VHDLTOOL
296 {x_("vhdl"), 1, FVHDL},
297 #endif
298 {NULL, 0, 0}
299 };
300
301 #define NOBLOAT ((BLOAT *)-1)
302
303 typedef struct Ibloat
304 {
305 CHAR *layer;
306 INTBIG amount;
307 struct Ibloat *nextbloat;
308 } BLOAT;
309
310 static BLOAT *io_curbloat = NOBLOAT;
311
312 /* working memory for "io_setuptechorder()" */
313 static INTBIG io_maxlayers;
314 static INTBIG io_mostlayers = 0;
315 static INTBIG *io_overlaporder;
316
317 /* miscellaneous */
318 FILE *io_fileout; /* channel for output */
319 jmp_buf io_filerror; /* nonlocal jump when I/O fails */
320 INTBIG io_cifbase; /* index used when writing CIF */
321 INTBIG io_postscriptfilenamekey; /* key for "IO_postscript_filename" */
322 INTBIG io_postscriptfiledatekey; /* key for "IO_postscript_filedate" */
323 INTBIG io_postscriptepsscalekey; /* key for "IO_postscript_EPS_scale" */
324 INTBIG io_verbose; /* 0: silent 1:chattier -1:graphical */
325 TOOL *io_tool; /* the I/O tool object */
326 INTBIG io_filetypeblib; /* Binary library disk file descriptor */
327 INTBIG io_filetypecif; /* CIF disk file descriptor */
328 INTBIG io_filetypedef; /* DEF disk file descriptor */
329 INTBIG io_filetypedxf; /* DXF disk file descriptor */
330 INTBIG io_filetypeeagle; /* EAGLE disk netlist file descriptor */
331 INTBIG io_filetypeecad; /* ECAD disk netlist file descriptor */
332 INTBIG io_filetypeedif; /* EDIF disk file descriptor */
333 INTBIG io_filetypegds; /* GDS disk file descriptor */
334 INTBIG io_filetypehpgl; /* HPGL disk file descriptor */
335 INTBIG io_filetypehpgl2; /* HPGL2 disk file descriptor */
336 INTBIG io_filetypel; /* L disk file descriptor */
337 INTBIG io_filetypelef; /* LEF disk file descriptor */
338 INTBIG io_filetypepads; /* PADS netlist disk file descriptor */
339 INTBIG io_filetypeps; /* PostScript disk file descriptor */
340 INTBIG io_filetypesdf; /* SDF disk file descriptor */
341 INTBIG io_filetypeskill; /* SKILL commands disk file descriptor */
342 INTBIG io_filetypesue; /* SUE disk file descriptor */
343 INTBIG io_filetypetlib; /* Text library disk file descriptor */
344 INTBIG io_filetypevhdl; /* VHDL disk file descriptor */
345 INTBIG io_libinputrecursivedepth; /* for recursing when reading dependent libraries */
346 INTBIG io_libinputreadmany; /* nonzero if reading dependent libraries */
347 static INTBIG io_state_key; /* key for "IO_state" */
348 static INTBIG io_libraryannouncetotal = 0; /* size of library announcement queue */
349 static INTBIG io_libraryannouncecount; /* number of libraries queued for announcement */
350 static LIBRARY **io_libraryannounce; /* list of libraries queued for announcement */
351
352 /* shared prototypes */
353 void io_compute_center(INTBIG xc, INTBIG yc, INTBIG x1, INTBIG y1,
354 INTBIG x2, INTBIG y2, INTBIG *cx, INTBIG *cy);
355
356 /* prototypes for local routines */
357 static double io_calc_angle(double r, double dx, double dy);
358 static void io_fixrtree(RTNODE*);
359 static void io_fixtechlayers(LIBRARY *lib);
360 static void io_unifylambdavalues(LIBRARY *lib);
361 static void io_libraryoptiondlog(void);
362 static void io_cdloptionsdialog(void);
363 static void io_sueoptionsdialog(void);
364 static void io_getversion(LIBRARY *lib, INTBIG *major, INTBIG *minor, INTBIG *detail);
365 static void io_convertallrelativetext(INTSML numvar, VARIABLE *firstvar);
366 static void io_convertrelativetext(UINTBIG *descript);
367 static void io_fixupnodeinst(NODEINST *ni, INTBIG dlx, INTBIG dly, INTBIG dhx, INTBIG dhy);
368 static void io_convertalltextdescriptors(INTSML numvar, VARIABLE *firstvar, INTBIG how);
369 static void io_converteverytextdescriptor(LIBRARY *lib, INTBIG how);
370 static void io_converttextdescriptor(UINTBIG *descript, INTBIG how);
371 static void io_setoutputbloat(CHAR *layer, INTBIG amount);
372
io_getstatebits(void)373 INTBIG *io_getstatebits(void)
374 {
375 REGISTER VARIABLE *var;
376 REGISTER INTBIG i, len;
377 static INTBIG mybits[NUMIOSTATEBITWORDS];
378
379 var = getvalkey((INTBIG)io_tool, VTOOL, -1, io_state_key);
380 if (var == NOVARIABLE)
381 {
382 for(i=1; i<NUMIOSTATEBITWORDS; i++) mybits[i] = 0;
383 mybits[0] = DXFFLATTENINPUT|GDSINARRAYS;
384 return(mybits);
385 }
386 if ((var->type&VISARRAY) != 0)
387 {
388 for(i=0; i<NUMIOSTATEBITWORDS; i++) mybits[i] = 0;
389 len = getlength(var);
390 for(i=0; i<len; i++) mybits[i] = ((INTBIG *)var->addr)[i];
391 return(mybits);
392 }
393 for(i=1; i<NUMIOSTATEBITWORDS; i++) mybits[i] = 0;
394 mybits[0] = var->addr;
395 return(mybits);
396 }
397
io_setstatebits(INTBIG * bits)398 void io_setstatebits(INTBIG *bits)
399 {
400 (void)setvalkey((INTBIG)io_tool, VTOOL, io_state_key, (INTBIG)bits,
401 VINTEGER|VISARRAY|(NUMIOSTATEBITWORDS<<VLENGTHSH));
402 }
403
io_init(INTBIG * argc,CHAR1 * argv[],TOOL * thistool)404 void io_init(INTBIG *argc, CHAR1 *argv[], TOOL *thistool)
405 {
406 INTBIG statebits[NUMIOSTATEBITWORDS], i;
407
408 /* nothing for pass 2 or 3 initialization */
409 if (thistool == NOTOOL || thistool == 0) return;
410
411 /* pass 1 initialization */
412 io_tool = thistool;
413 io_state_key = makekey(x_("IO_state"));
414 io_postscriptfilenamekey = makekey(x_("IO_postscript_filename"));
415 io_postscriptfiledatekey = makekey(x_("IO_postscript_filedate"));
416 io_postscriptepsscalekey = makekey(x_("IO_postscript_EPS_scale"));
417 nextchangequiet();
418 for(i=1; i<NUMIOSTATEBITWORDS; i++) statebits[i] = 0;
419 statebits[0] = DXFFLATTENINPUT|GDSINARRAYS|HPGL2;
420 (void)setvalkey((INTBIG)io_tool, VTOOL, io_state_key, (INTBIG)statebits,
421 VINTEGER|VISARRAY|(NUMIOSTATEBITWORDS<<VLENGTHSH)|VDONTSAVE);
422 io_verbose = 0;
423
424 DiaDeclareHook(x_("libopt"), &ioverp, io_libraryoptiondlog);
425 DiaDeclareHook(x_("cdlopt"), &iobloatlp, io_cdloptionsdialog);
426 DiaDeclareHook(x_("sueopt"), &iobloatap, io_sueoptionsdialog);
427
428 /* create disk file descriptors */
429 io_filetypeblib = setupfiletype(x_("elib"), x_("*.elib"), MACFSTAG('Elec'), TRUE, x_("blib"), _("Binary library"));
430 io_filetypecif = setupfiletype(x_("cif"), x_("*.cif"), MACFSTAG('TEXT'), FALSE, x_("cif"), _("CIF"));
431 io_filetypedef = setupfiletype(x_("def"), x_("*.def"), MACFSTAG('TEXT'), FALSE, x_("def"), _("DEF"));
432 io_filetypedxf = setupfiletype(x_("dxf"), x_("*.dxf"), MACFSTAG('TEXT'), FALSE, x_("dxf"), _("AutoCAD DXF"));
433 io_filetypeeagle = setupfiletype(x_("txt"), x_("*.txt"), MACFSTAG('TEXT'), FALSE, x_("eagle"), _("Eagle netlist"));
434 io_filetypeecad = setupfiletype(x_("enl"), x_("*.enl"), MACFSTAG('TEXT'), FALSE, x_("ecad"), _("ECAD netlist"));
435 io_filetypeedif = setupfiletype(x_("edif"), x_("*.edif;*.ed?"), MACFSTAG('TEXT'), FALSE, x_("edif"), _("EDIF"));
436 io_filetypegds = setupfiletype(x_("gds"), x_("*.gds"), MACFSTAG('GDS '), TRUE, x_("gds"), _("GDS II"));
437 io_filetypehpgl = setupfiletype(x_("hpgl"), x_("*.hpgl"), MACFSTAG('TEXT'), FALSE, x_("hpgl"), _("HPGL"));
438 io_filetypehpgl2 = setupfiletype(x_("hpgl2"),x_("*.hpgl2"), MACFSTAG('TEXT'), FALSE, x_("hpgl2"), _("HPGL/2"));
439 io_filetypel = setupfiletype(x_("l"), x_("*.l"), MACFSTAG('TEXT'), FALSE, x_("l"), _("L"));
440 io_filetypelef = setupfiletype(x_("lef"), x_("*.lef"), MACFSTAG('TEXT'), FALSE, x_("lef"), _("LEF"));
441 io_filetypepads = setupfiletype(x_("asc"), x_("*.asc"), MACFSTAG('TEXT'), FALSE, x_("pad"), _("PADS netlist"));
442 io_filetypeps = setupfiletype(x_("ps"), x_("*.ps;*.eps"), MACFSTAG('TEXT'), FALSE, x_("ps"), _("PostScript"));
443 io_filetypesdf = setupfiletype(x_("sdf"), x_("*.sdf"), MACFSTAG('TEXT'), FALSE, x_("sdf"), _("SDF"));
444 io_filetypeskill = setupfiletype(x_("il"), x_("*.il"), MACFSTAG('TEXT'), FALSE, x_("skill"), _("SKILL commands"));
445 io_filetypesue = setupfiletype(x_("sue"), x_("*.sue"), MACFSTAG('TEXT'), FALSE, x_("sue"), _("SUE"));
446 io_filetypetlib = setupfiletype(x_("txt"), x_("*.txt"), MACFSTAG('TEXT'), FALSE, x_("tlib"), _("Text library"));
447 io_filetypevhdl = setupfiletype(x_("vhdl"), x_("*.vhdl;*.vhd"), MACFSTAG('TEXT'), FALSE, x_("vhdl"), _("VHDL"));
448
449 io_initcif();
450 io_initdef();
451 io_initdxf();
452 io_initedif();
453 io_initgds();
454 #ifdef FORCECADENCE
455 io_initskill();
456 #endif
457 }
458
io_done(void)459 void io_done(void)
460 {
461 #ifdef DEBUGMEMORY
462 if (io_mostlayers > 0) efree((CHAR *)io_overlaporder);
463 io_freebininmemory();
464 io_freebinoutmemory();
465 io_freepostscriptmemory();
466 io_freetextinmemory();
467 io_freecifinmemory();
468 io_freecifparsmemory();
469 io_freecifoutmemory();
470 io_freedefimemory();
471 io_freedxfmemory();
472 io_freeedifinmemory();
473 io_freegdsinmemory();
474 io_freegdsoutmemory();
475 io_freelefimemory();
476 io_freesdfimemory();
477 io_freesuememory();
478 if (io_libraryannouncetotal > 0)
479 efree((CHAR *)io_libraryannounce);
480 #endif
481 }
482
io_slice(void)483 void io_slice(void)
484 {
485 ttyputmsg(M_("Input and Output are performed with the 'library' command"));
486 ttyputmsg(M_("...I/O tool turned off"));
487 toolturnoff(io_tool, FALSE);
488 }
489
io_set(INTBIG count,CHAR * par[])490 void io_set(INTBIG count, CHAR *par[])
491 {
492 REGISTER INTBIG l;
493 REGISTER INTBIG *curstate, scale, wid, hei;
494 REGISTER NODEPROTO *np;
495 REGISTER CHAR *pp;
496 REGISTER VARIABLE *var;
497 INTBIG arcres, arcsag;
498
499 if (count == 0)
500 {
501 count = ttygetparam(M_("IO option:"), &io_iop, MAXPARS, par);
502 if (count == 0)
503 {
504 ttyputerr(M_("Aborted"));
505 return;
506 }
507 }
508 l = estrlen(pp = par[0]);
509
510 /* get current state of I/O tool */
511 curstate = io_getstatebits();
512
513 /* check for bloating specifications */
514 if (namesamen(pp, x_("bloat-output"), l) == 0)
515 {
516 if (count <= 1)
517 {
518 io_setoutputbloat(x_(""), 0);
519 return;
520 }
521 if (count < 3)
522 {
523 ttyputusage(x_("telltool io bloat-output LAYER AMOUNT"));
524 return;
525 }
526 io_setoutputbloat(par[1], myatoi(par[2]));
527 return;
528 }
529
530 /* check for format specifications */
531 if (namesamen(pp, x_("plot"), l) == 0)
532 {
533 if (count <= 1)
534 {
535 ttyputusage(x_("telltool io plot OPTIONS"));
536 return;
537 }
538
539 l = estrlen(pp = par[1]);
540 if (namesamen(pp, x_("not"), l) == 0)
541 {
542 if (count <= 2)
543 {
544 ttyputusage(x_("telltool io plot not OPTION"));
545 return;
546 }
547 l = estrlen(pp = par[2]);
548 if (namesamen(pp, x_("focus"), l) == 0)
549 {
550 curstate[0] &= ~(PLOTFOCUS|PLOTFOCUSDPY);
551 io_setstatebits(curstate);
552 ttyputverbose(M_("Plot output will display entire cell"));
553 return;
554 }
555 if (namesamen(pp, x_("include-date"), l) == 0)
556 {
557 curstate[0] &= ~PLOTDATES;
558 io_setstatebits(curstate);
559 ttyputverbose(M_("Plot output will not include dates"));
560 return;
561 }
562 ttyputbadusage(x_("telltool io plot not"));
563 return;
564 }
565 if (namesamen(pp, x_("focus-highlighted"), l) == 0 && l >= 7)
566 {
567 curstate[0] = (curstate[0] & ~PLOTFOCUSDPY) | PLOTFOCUS;
568 io_setstatebits(curstate);
569 ttyputverbose(M_("Plot output will focus on highlighted area"));
570 return;
571 }
572 if (namesamen(pp, x_("focus-window"), l) == 0 && l >= 7)
573 {
574 curstate[0] |= (PLOTFOCUSDPY|PLOTFOCUS);
575 io_setstatebits(curstate);
576 ttyputverbose(M_("Plot output will focus on highlighted area"));
577 return;
578 }
579 if (namesamen(pp, x_("include-date"), l) == 0)
580 {
581 curstate[0] |= PLOTDATES;
582 io_setstatebits(curstate);
583 ttyputverbose(M_("Plot output will include dates"));
584 return;
585 }
586 ttyputbadusage(x_("telltool io plot"));
587 return;
588 }
589
590 /* check for binary specifications */
591 if (namesamen(pp, x_("binary"), l) == 0)
592 {
593 l = estrlen(pp = par[1]);
594 if (namesamen(pp, x_("no-backup"), l) == 0 && l >= 4)
595 {
596 curstate[0] = (curstate[0] & ~BINOUTBACKUP) | BINOUTNOBACK;
597 io_setstatebits(curstate);
598 ttyputverbose(M_("Binary output will not keep backups"));
599 return;
600 }
601 if (namesamen(pp, x_("one-level-backup"), l) == 0)
602 {
603 curstate[0] = (curstate[0] & ~BINOUTBACKUP) | BINOUTONEBACK;
604 io_setstatebits(curstate);
605 ttyputverbose(M_("Binary output will keep one backup"));
606 return;
607 }
608 if (namesamen(pp, x_("many-level-backup"), l) == 0)
609 {
610 curstate[0] = (curstate[0] & ~BINOUTBACKUP) | BINOUTFULLBACK;
611 io_setstatebits(curstate);
612 ttyputverbose(M_("Binary output will keep full backups"));
613 return;
614 }
615
616 if (namesamen(pp, x_("no-check"), l) == 0 && l >= 4)
617 {
618 curstate[0] &= ~CHECKATWRITE;
619 io_setstatebits(curstate);
620 ttyputverbose(M_("Binary output will not check the database"));
621 return;
622 }
623 if (namesamen(pp, x_("check"), l) == 0)
624 {
625 curstate[0] |= CHECKATWRITE;
626 io_setstatebits(curstate);
627 ttyputverbose(M_("Binary output will check the database"));
628 return;
629 }
630 ttyputbadusage(x_("telltool io binary"));
631 return;
632 }
633
634 if (namesamen(pp, x_("cif"), l) == 0)
635 {
636 if (count <= 1)
637 {
638 ttyputusage(x_("telltool io cif (input|output)"));
639 return;
640 }
641 l = estrlen(pp = par[1]);
642 if (namesamen(pp, x_("input"), l) == 0)
643 {
644 if (count <= 2)
645 {
646 ttyputusage(x_("telltool io cif input OPTIONS"));
647 return;
648 }
649 l = estrlen(pp = par[2]);
650 switch (*pp)
651 {
652 case 'r':
653 curstate[0] &= ~CIFINSQUARE;
654 io_setstatebits(curstate);
655 ttyputverbose(M_("CIF wires will have rounded ends"));
656 break;
657 case 's':
658 curstate[0] |= CIFINSQUARE;
659 io_setstatebits(curstate);
660 ttyputverbose(M_("CIF wires will have squared ends"));
661 break;
662 default:
663 ttyputbadusage(x_("telltool io cif input"));
664 }
665 return;
666 }
667 if (namesamen(pp, x_("output"), l) == 0)
668 {
669 if (count <= 2)
670 {
671 ttyputusage(x_("telltool io cif output OPTIONS"));
672 return;
673 }
674
675 l = estrlen(pp = par[2]);
676 if (namesamen(pp, x_("fully-instantiated"), l) == 0)
677 {
678 curstate[0] &= ~CIFOUTEXACT;
679 io_setstatebits(curstate);
680 ttyputverbose(M_("CIF generation will include all cells"));
681 return;
682 }
683 if (namesamen(pp, x_("exactly-as-displayed"), l) == 0)
684 {
685 curstate[0] |= CIFOUTEXACT;
686 io_setstatebits(curstate);
687 ttyputverbose(M_("CIF generation will duplicate screen"));
688 return;
689 }
690 if (namesamen(pp, x_("merge-boxes"), l) == 0)
691 {
692 curstate[0] |= CIFOUTMERGE;
693 io_setstatebits(curstate);
694 ttyputverbose(M_("CIF generation will merge boxes"));
695 return;
696 }
697 if (namesamen(pp, x_("individual-boxes"), l) == 0 && l >= 3)
698 {
699 curstate[0] &= ~CIFOUTMERGE;
700 io_setstatebits(curstate);
701 ttyputverbose(M_("CIF generation will list individual boxes"));
702 return;
703 }
704 if (namesamen(pp, x_("include-cloak-layer"), l) == 0 && l >= 3)
705 {
706 curstate[0] |= CIFOUTADDDRC;
707 io_setstatebits(curstate);
708 ttyputverbose(M_("CIF generation will include DRC cloak layer"));
709 return;
710 }
711 if (namesamen(pp, x_("ignore-cloak-layer"), l) == 0 && l >= 2)
712 {
713 curstate[0] &= ~CIFOUTADDDRC;
714 io_setstatebits(curstate);
715 ttyputverbose(M_("CIF generation will ignore DRC cloak layer"));
716 return;
717 }
718 if (namesamen(pp, x_("normalized"), l) == 0 && l >= 3)
719 {
720 curstate[0] |= CIFOUTNORMALIZE;
721 io_setstatebits(curstate);
722 ttyputverbose(M_("CIF generation will normalize coordinates"));
723 return;
724 }
725 if (namesamen(pp, x_("not-normalized"), l) == 0 && l >= 3)
726 {
727 curstate[0] &= ~CIFOUTNORMALIZE;
728 io_setstatebits(curstate);
729 ttyputverbose(M_("CIF generation will use cell coordinates"));
730 return;
731 }
732 if (namesamen(pp, x_("instantiate-top"), l) == 0 && l >= 3)
733 {
734 curstate[0] &= ~CIFOUTNOTOPCALL;
735 io_setstatebits(curstate);
736 ttyputverbose(M_("CIF generation will instantiate top-level cell"));
737 return;
738 }
739 if (namesamen(pp, x_("dont-instantiate-top"), l) == 0 && l >= 3)
740 {
741 curstate[0] |= CIFOUTNOTOPCALL;
742 io_setstatebits(curstate);
743 ttyputverbose(M_("CIF generation will not instantiate top-level cell"));
744 return;
745 }
746 if (namesamen(pp, x_("highlight-resolution"), l) == 0 && l >= 3)
747 {
748 curstate[1] |= CIFRESHIGH;
749 io_setstatebits(curstate);
750 ttyputverbose(M_("CIF generation will highlight resolution errors"));
751 return;
752 }
753 if (namesamen(pp, x_("hide-resolution"), l) == 0 && l >= 3)
754 {
755 curstate[1] &= ~CIFRESHIGH;
756 io_setstatebits(curstate);
757 ttyputverbose(M_("CIF generation will not highlight resolution errors"));
758 return;
759 }
760 ttyputbadusage(x_("telltool io cif output"));
761 }
762 ttyputbadusage(x_("telltool io cif"));
763 return;
764 }
765
766 if (namesamen(pp, x_("gds"), l) == 0)
767 {
768 if (count <= 1)
769 {
770 ttyputusage(x_("telltool io gds OPTION"));
771 return;
772 }
773 l = estrlen(pp = par[1]);
774 if (namesamen(pp, x_("input"), l) == 0)
775 {
776 if (count <= 2)
777 {
778 ttyputusage(x_("telltool io gds input OPTION"));
779 return;
780 }
781 l = estrlen(pp = par[2]);
782 if (namesamen(pp, x_("text"), l) == 0)
783 {
784 curstate[0] |= GDSINTEXT;
785 io_setstatebits(curstate);
786 ttyputverbose(M_("GDS input includes text"));
787 return;
788 }
789 if (namesamen(pp, x_("no-text"), l) == 0 && l >= 4)
790 {
791 curstate[0] &= ~GDSINTEXT;
792 io_setstatebits(curstate);
793 ttyputverbose(M_("GDS input ignores text"));
794 return;
795 }
796 if (namesamen(pp, x_("expand"), l) == 0)
797 {
798 curstate[0] |= GDSINEXPAND;
799 io_setstatebits(curstate);
800 ttyputverbose(M_("GDS input expands instances"));
801 return;
802 }
803 if (namesamen(pp, x_("no-expand"), l) == 0 && l >= 4)
804 {
805 curstate[0] &= ~GDSINEXPAND;
806 io_setstatebits(curstate);
807 ttyputverbose(M_("GDS input does not expand instances"));
808 return;
809 }
810 if (namesamen(pp, x_("arrays"), l) == 0)
811 {
812 curstate[0] |= GDSINARRAYS;
813 io_setstatebits(curstate);
814 ttyputverbose(M_("GDS input instantiates arrays"));
815 return;
816 }
817 if (namesamen(pp, x_("no-arrays"), l) == 0 && l >= 4)
818 {
819 curstate[0] &= ~GDSINARRAYS;
820 io_setstatebits(curstate);
821 ttyputverbose(M_("GDS input does not instantiate arrays"));
822 return;
823 }
824 if (namesamen(pp, x_("unknown-layers"), l) == 0)
825 {
826 curstate[0] |= GDSINIGNOREUKN;
827 io_setstatebits(curstate);
828 ttyputverbose(M_("GDS input includes unknown layers"));
829 return;
830 }
831 if (namesamen(pp, x_("no-unknown-layers"), l) == 0 && l >= 4)
832 {
833 curstate[0] &= ~GDSINIGNOREUKN;
834 io_setstatebits(curstate);
835 ttyputverbose(M_("GDS input ignores unknown layers"));
836 return;
837 }
838 ttyputbadusage(x_("telltool io gds input"));
839 return;
840 }
841 if (namesamen(pp, x_("output"), l) == 0)
842 {
843 if (count <= 2)
844 {
845 ttyputusage(x_("telltool io gds output OPTION"));
846 return;
847 }
848 l = estrlen(pp = par[2]);
849 if (namesamen(pp, x_("merge-boxes"), l) == 0)
850 {
851 curstate[0] |= GDSOUTMERGE;
852 io_setstatebits(curstate);
853 ttyputverbose(M_("GDS generation will merge boxes"));
854 return;
855 }
856 if (namesamen(pp, x_("individual-boxes"), l) == 0 && l >= 3)
857 {
858 curstate[0] &= ~GDSOUTMERGE;
859 io_setstatebits(curstate);
860 ttyputverbose(M_("GDS generation will list individual boxes"));
861 return;
862 }
863 if (namesamen(pp, x_("include-cloak-layer"), l) == 0 && l >= 3)
864 {
865 curstate[0] |= GDSOUTADDDRC;
866 io_setstatebits(curstate);
867 ttyputverbose(M_("GDS generation will include DRC cloak layer"));
868 return;
869 }
870 if (namesamen(pp, x_("ignore-cloak-layer"), l) == 0 && l >= 2)
871 {
872 curstate[0] &= ~GDSOUTADDDRC;
873 io_setstatebits(curstate);
874 ttyputverbose(M_("GDS generation will ignore DRC cloak layer"));
875 return;
876 }
877 if (namesamen(pp, x_("arc-resolution"), l) == 0 && l >= 5)
878 {
879 getcontoursegmentparameters(&arcres, &arcsag);
880 if (count > 3) arcres = atofr(par[3]) * 10 / WHOLE;
881 ttyputverbose(M_("GDS arc generation will create a line every %s degrees"),
882 frtoa(arcres*WHOLE/10));
883 setcontoursegmentparameters(arcres, arcsag);
884 return;
885 }
886 if (namesamen(pp, x_("arc-sag"), l) == 0 && l >= 5)
887 {
888 getcontoursegmentparameters(&arcres, &arcsag);
889 if (count > 3) arcsag = atola(par[3], 0);
890 ttyputverbose(M_("GDS arc generation will sag no more than %s"), latoa(arcsag, 0));
891 setcontoursegmentparameters(arcres, arcsag);
892 return;
893 }
894 ttyputbadusage(x_("telltool io gds output"));
895 return;
896 }
897 ttyputbadusage(x_("telltool io gds"));
898 return;
899 }
900
901 if (namesamen(pp, x_("dxf"), l) == 0)
902 {
903 if (count <= 1)
904 {
905 ttyputusage(x_("telltool io dxf OPTION"));
906 return;
907 }
908 l = estrlen(pp = par[1]);
909 if (namesamen(pp, x_("acceptable-layers"), l) == 0)
910 {
911 if (count <= 2)
912 {
913 if ((curstate[0]&DXFALLLAYERS) == 0)
914 ttyputmsg(M_("DXF input will accept only layers listed by technology")); else
915 ttyputmsg(M_("DXF input will accept all layers"));
916 return;
917 }
918 l = estrlen(pp = par[2]);
919 if (namesamen(pp, x_("all"), l) == 0)
920 {
921 curstate[0] |= DXFALLLAYERS;
922 io_setstatebits(curstate);
923 ttyputverbose(M_("DXF input will accept all layers"));
924 return;
925 }
926 if (namesamen(pp, x_("restrict"), l) == 0)
927 {
928 curstate[0] &= ~DXFALLLAYERS;
929 io_setstatebits(curstate);
930 ttyputverbose(M_("DXF input will accept only layers listed by technology"));
931 return;
932 }
933 }
934 if (namesamen(pp, x_("flatten-input"), l) == 0)
935 {
936 curstate[0] |= DXFFLATTENINPUT;
937 io_setstatebits(curstate);
938 ttyputverbose(M_("DXF input will flatten input blocks"));
939 return;
940 }
941 if (namesamen(pp, x_("not-flatten-input"), l) == 0)
942 {
943 curstate[0] &= ~DXFFLATTENINPUT;
944 io_setstatebits(curstate);
945 ttyputverbose(M_("DXF input will retain input hierarchy"));
946 return;
947 }
948 ttyputbadusage(x_("telltool io dxf"));
949 return;
950 }
951
952 if (namesamen(pp, x_("postscript"), l) == 0)
953 {
954 if (count <= 1)
955 {
956 ttyputusage(x_("telltool io postscript OPTION"));
957 return;
958 }
959 l = estrlen(pp = par[1]);
960 if (namesamen(pp, x_("encapsulated"), l) == 0)
961 {
962 curstate[0] |= EPSPSCRIPT;
963 io_setstatebits(curstate);
964 ttyputverbose(M_("PostScript output will be encapsulated format"));
965 return;
966 }
967 if (namesamen(pp, x_("plain"), l) == 0 && l >= 2)
968 {
969 curstate[0] &= ~EPSPSCRIPT;
970 io_setstatebits(curstate);
971 ttyputverbose(M_("PostScript output will be plain format"));
972 return;
973 }
974 if (namesamen(pp, x_("color"), l) == 0)
975 {
976 curstate[0] = (curstate[0] & ~PSCOLOR2) | PSCOLOR1;
977 io_setstatebits(curstate);
978 ttyputverbose(M_("PostScript output will use color"));
979 return;
980 }
981 if (namesamen(pp, x_("merged-color"), l) == 0 && l >= 2)
982 {
983 curstate[0] = (curstate[0] & ~PSCOLOR1) | PSCOLOR2;
984 io_setstatebits(curstate);
985 ttyputverbose(M_("PostScript output will use merged color"));
986 return;
987 }
988 if (namesamen(pp, x_("stippled-color"), l) == 0 && l >= 2)
989 {
990 curstate[0] |= PSCOLOR1 | PSCOLOR2;
991 io_setstatebits(curstate);
992 ttyputverbose(M_("PostScript output will use color"));
993 return;
994 }
995 if (namesamen(pp, x_("gray-scale"), l) == 0)
996 {
997 curstate[0] &= ~(PSCOLOR1|PSCOLOR2);
998 io_setstatebits(curstate);
999 ttyputverbose(M_("PostScript output will be gray-scale"));
1000 return;
1001 }
1002 if (namesamen(pp, x_("rotate"), l) == 0)
1003 {
1004 curstate[0] |= PSROTATE;
1005 curstate[1] &= ~PSAUTOROTATE;
1006 io_setstatebits(curstate);
1007 ttyputverbose(M_("PostScript output will be rotated 90 degrees"));
1008 return;
1009 }
1010 if (namesamen(pp, x_("no-rotate"), l) == 0)
1011 {
1012 curstate[0] &= ~PSROTATE;
1013 curstate[1] &= ~PSAUTOROTATE;
1014 io_setstatebits(curstate);
1015 ttyputverbose(M_("PostScript output will appear unrotated"));
1016 return;
1017 }
1018 if (namesamen(pp, x_("auto-rotate"), l) == 0)
1019 {
1020 curstate[0] &= ~PSROTATE;
1021 curstate[1] |= PSAUTOROTATE;
1022 io_setstatebits(curstate);
1023 ttyputverbose(M_("PostScript output will automatically rotate to fit best"));
1024 return;
1025 }
1026 if (namesamen(pp, x_("margin"), l) == 0 && l >= 2)
1027 {
1028 if (count == 3)
1029 {
1030 wid = atofr(par[2]);
1031 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_postscript_margin"), wid, VFRACT);
1032 } else
1033 {
1034 var = getval((INTBIG)io_tool, VTOOL, VFRACT, x_("IO_postscript_margin"));
1035 if (var == NOVARIABLE) wid = muldiv(DEFAULTPSMARGIN, WHOLE, 75); else
1036 wid = var->addr;
1037 }
1038 ttyputverbose(M_("PostScript output will use a %s-wide margin"), frtoa(wid));
1039 return;
1040 }
1041 if (namesamen(pp, x_("plotter"), l) == 0 && l >= 2)
1042 {
1043 curstate[0] |= PSPLOTTER;
1044 io_setstatebits(curstate);
1045 if (count == 3)
1046 {
1047 wid = atofr(par[2]);
1048 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_postscript_width"), wid, VFRACT);
1049 ttyputverbose(M_("PostScript output will assume a %s-wide plotter"), frtoa(wid));
1050 } else
1051 ttyputverbose(M_("PostScript output will assume a continuous-roll plotter"));
1052 return;
1053 }
1054 if (namesamen(pp, x_("printer"), l) == 0 && l >= 2)
1055 {
1056 curstate[0] &= ~PSPLOTTER;
1057 io_setstatebits(curstate);
1058 if (count == 4)
1059 {
1060 wid = atofr(par[2]);
1061 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_postscript_width"), wid, VFRACT);
1062 hei = atofr(par[3]);
1063 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_postscript_height"), hei, VFRACT);
1064 ttyputverbose(M_("PostScript output will assume a %s x %s page"),
1065 frtoa(wid), frtoa(hei));
1066 } else
1067 ttyputverbose(M_("PostScript output will be assume a fixed-size sheet"));
1068 return;
1069 }
1070 if (namesamen(pp, x_("unsynchronize"), l) == 0)
1071 {
1072 np = el_curlib->curnodeproto;
1073 if (np == NONODEPROTO)
1074 {
1075 ttyputerr(M_("Edit a cell before removing synchronization"));
1076 return;
1077 }
1078 if (getvalkey((INTBIG)np, VNODEPROTO, VSTRING, io_postscriptfilenamekey) != NOVARIABLE)
1079 {
1080 (void)delvalkey((INTBIG)np, VNODEPROTO, io_postscriptfilenamekey);
1081 ttyputverbose(M_("Cell %s no longer synchronized to PostScript disk file"),
1082 describenodeproto(np));
1083 }
1084 return;
1085 }
1086 if (namesamen(pp, x_("synchronize"), l) == 0 && l >= 2)
1087 {
1088 if (count <= 2)
1089 {
1090 ttyputusage(x_("telltool io postscript synchronize FILENAME"));
1091 return;
1092 }
1093 np = el_curlib->curnodeproto;
1094 if (np == NONODEPROTO)
1095 {
1096 ttyputerr(M_("Edit a cell to synchronize it to a PostScript file"));
1097 return;
1098 }
1099 (void)setvalkey((INTBIG)np, VNODEPROTO, io_postscriptfilenamekey,
1100 (INTBIG)par[1], VSTRING);
1101 ttyputverbose(M_("Cell %s synchronized to PostScript file %s"),
1102 describenodeproto(np), par[1]);
1103 return;
1104 }
1105 ttyputbadusage(x_("telltool io postscript"));
1106 return;
1107 }
1108
1109 if (namesamen(pp, x_("hpgl"), l) == 0)
1110 {
1111 if (count <= 1)
1112 {
1113 ttyputusage(x_("telltool io hpgl (1|2)"));
1114 return;
1115 }
1116 l = estrlen(pp = par[1]);
1117 if (namesamen(pp, x_("1"), l) == 0)
1118 {
1119 curstate[0] &= ~HPGL2;
1120 io_setstatebits(curstate);
1121 ttyputmsg(M_("HPGL output will use older (version 1) format"));
1122 return;
1123 }
1124 if (namesamen(pp, x_("2"), l) == 0)
1125 {
1126 curstate[0] |= HPGL2;
1127 io_setstatebits(curstate);
1128 ttyputverbose(M_("HPGL output will use newer (HPGL/2) format"));
1129 if (count >= 4 && namesamen(par[2], x_("scale"), estrlen(par[2])) == 0)
1130 {
1131 scale = myatoi(par[3]);
1132 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_hpgl2_scale"),
1133 scale, VINTEGER);
1134 ttyputverbose(M_("HPGL/2 plots will scale at %ld %ss per pixel"),
1135 scale, unitsname(el_units));
1136 }
1137 return;
1138 }
1139 ttyputbadusage(x_("telltool io hpgl"));
1140 return;
1141 }
1142
1143 if (namesamen(pp, x_("edif"), l) == 0)
1144 {
1145 if (count <= 1)
1146 {
1147 ttyputusage(x_("telltool io edif (schematic|netlist)"));
1148 return;
1149 }
1150 l = estrlen(pp = par[1]);
1151 if (namesamen(pp, x_("schematic"), l) == 0)
1152 {
1153 curstate[0] |= EDIFSCHEMATIC;
1154 io_setstatebits(curstate);
1155 ttyputverbose(M_("EDIF output will write schematics"));
1156 return;
1157 }
1158 if (namesamen(pp, x_("netlist"), l) == 0)
1159 {
1160 curstate[0] &= ~EDIFSCHEMATIC;
1161 io_setstatebits(curstate);
1162 ttyputverbose(M_("EDIF output will write netlists"));
1163 return;
1164 }
1165 ttyputbadusage(x_("telltool io edif"));
1166 return;
1167 }
1168
1169 if (namesamen(pp, x_("verbose"), l) == 0)
1170 {
1171 if (count <= 1)
1172 {
1173 ttyputusage(x_("telltool io verbose OPTION"));
1174 return;
1175 }
1176 l = estrlen(pp = par[1]);
1177 if (namesamen(pp, x_("off"), l) == 0 && l >= 2)
1178 {
1179 io_verbose = 0;
1180 ttyputverbose(M_("I/O done silently"));
1181 return;
1182 }
1183 if (namesamen(pp, x_("on"), l) == 0 && l >= 2)
1184 {
1185 io_verbose = 1;
1186 ttyputverbose(M_("I/O prints status"));
1187 return;
1188 }
1189 if (namesamen(pp, x_("graphical"), l) == 0 && l >= 1)
1190 {
1191 io_verbose = -1;
1192 ttyputverbose(M_("I/O shows graphical progress"));
1193 return;
1194 }
1195 ttyputbadusage(x_("telltool io verbose"));
1196 return;
1197 }
1198
1199 ttyputbadusage(x_("telltool io"));
1200 }
1201
1202 /*
1203 * make I/O requests of this tool:
1204 *
1205 * "read" TAKES: LIBRARY to read and string style
1206 * "write" TAKES: LIBRARY to write and string style
1207 * "verbose" TAKES: new verbose factor, RETURNS: old verbose factor
1208 */
io_request(CHAR * command,va_list ap)1209 INTBIG io_request(CHAR *command, va_list ap)
1210 {
1211 REGISTER LIBRARY *lib;
1212 REGISTER INTBIG i, j, len, format;
1213 REGISTER BOOLEAN err;
1214 REGISTER INTBIG arg1, arg3;
1215 CHAR *arg2;
1216
1217 if (namesame(command, x_("verbose")) == 0)
1218 {
1219 i = io_verbose;
1220 io_verbose = va_arg(ap, INTBIG);
1221 return(i);
1222 }
1223
1224 /* get the arguments */
1225 arg1 = va_arg(ap, INTBIG);
1226 arg2 = va_arg(ap, CHAR*);
1227
1228 /* find desired library and format */
1229 lib = (LIBRARY *)arg1;
1230 format = -1;
1231 len = estrlen(arg2);
1232 for(i=0; io_formatlist[i].name != 0; i++)
1233 if (namesamen(arg2, io_formatlist[i].name, len) == 0 && len >= io_formatlist[i].required)
1234 {
1235 format = io_formatlist[i].bits;
1236 break;
1237 }
1238 if (format < 0)
1239 {
1240 ttyputerr(M_("Unknown I/O format: %s"), arg2);
1241 return(1);
1242 }
1243
1244 if (namesame(command, x_("write")) == 0)
1245 {
1246 /* announce the beginning of library output */
1247 for(i=0; i<el_maxtools; i++)
1248 if (el_tools[i].writelibrary != 0)
1249 (*el_tools[i].writelibrary)(lib, FALSE);
1250
1251 switch (format)
1252 {
1253 case FBINARY:
1254 err = io_writebinlibrary(lib, FALSE);
1255 break;
1256
1257 case FBINARYNOBACKUP:
1258 err = io_writebinlibrary(lib, TRUE);
1259 break;
1260
1261 case FCIF:
1262 err = io_writeciflibrary(lib);
1263 break;
1264
1265 case FDXF:
1266 err = io_writedxflibrary(lib);
1267 break;
1268
1269 case FEAGLE:
1270 err = io_writeeaglelibrary(lib);
1271 break;
1272
1273 case FECAD:
1274 err = io_writeecadlibrary(lib);
1275 break;
1276
1277 case FEDIF:
1278 err = io_writeediflibrary(lib);
1279 break;
1280
1281 case FGDS:
1282 err = io_writegdslibrary(lib);
1283 break;
1284
1285 case FHPGL:
1286 err = io_writehpgllibrary(lib);
1287 break;
1288
1289 case FL:
1290 err = io_writellibrary(lib);
1291 break;
1292
1293 case FLEF:
1294 err = io_writeleflibrary(lib);
1295 break;
1296
1297 case FPADS:
1298 err = io_writepadslibrary(lib);
1299 break;
1300
1301 case FPOSTSCRIPT:
1302 case FPRINTEDPOSTSCRIPT:
1303 err = io_writepostscriptlibrary(lib,
1304 (BOOLEAN)(format == FPRINTEDPOSTSCRIPT));
1305 break;
1306
1307 #if defined(MACOS) && !defined(MACOSX)
1308 case FQUICKDRAW:
1309 err = io_writequickdrawlibrary(lib);
1310 break;
1311 #endif
1312
1313 #ifdef FORCECADENCE
1314 case FSKILL:
1315 err = io_writeskilllibrary(lib);
1316 break;
1317 #endif
1318
1319 case FTEXT:
1320 err = io_writetextlibrary(lib);
1321 break;
1322
1323 default:
1324 for(i=0; io_formatlist[i].name != 0; i++)
1325 if (io_formatlist[i].bits == format)
1326 {
1327 ttyputerr(M_("Cannot write %s files"), io_formatlist[i].name);
1328 return(1);
1329 }
1330 }
1331
1332 /* announce the ending of library output */
1333 if (err) return(1);
1334 for(i=0; i<el_maxtools; i++)
1335 if (el_tools[i].writelibrary != 0)
1336 (*el_tools[i].writelibrary)(lib, TRUE);
1337 return(0);
1338 }
1339
1340 if (namesame(command, x_("read")) == 0)
1341 {
1342 arg3 = va_arg(ap, INTBIG);
1343 io_libinputrecursivedepth = io_libinputreadmany = 0;
1344 io_libraryannouncecount = 0;
1345 switch (format)
1346 {
1347 case FBINARY:
1348 err = io_readbinlibrary(lib);
1349 /* make sure that the lambda values are consistent */
1350 if (!err) io_unifylambdavalues(lib);
1351 break;
1352
1353 case FCIF:
1354 err = io_readciflibrary(lib);
1355 break;
1356
1357 case FDEF:
1358 err = io_readdeflibrary(lib);
1359 break;
1360
1361 case FDXF:
1362 err = io_readdxflibrary(lib);
1363 break;
1364
1365 case FEDIF:
1366 err = io_readediflibrary(lib);
1367 break;
1368
1369 case FGDS:
1370 err = io_readgdslibrary(lib, arg3);
1371 break;
1372
1373 case FLEF:
1374 err = io_readleflibrary(lib);
1375 break;
1376
1377 case FSDF:
1378 err = io_readsdflibrary(lib);
1379 break;
1380
1381 case FSUE:
1382 err = io_readsuelibrary(lib);
1383 break;
1384
1385 case FTEXT:
1386 err = io_readtextlibrary(lib);
1387 /* make sure that the lambda values are consistent */
1388 if (!err) io_unifylambdavalues(lib);
1389 break;
1390
1391 #if VHDLTOOL
1392 case FVHDL:
1393 err = io_readvhdllibrary(lib);
1394 break;
1395 #endif
1396
1397 default:
1398 for(i=0; io_formatlist[i].name != 0; i++)
1399 if (io_formatlist[i].bits == format)
1400 {
1401 ttyputerr(M_("Cannot read %s files"), io_formatlist[i].name);
1402 return(1);
1403 }
1404 }
1405
1406 /* announce the completion of library input */
1407 if (err) return(1);
1408 io_queuereadlibraryannouncement(lib);
1409 for(i=0; i<el_maxtools; i++)
1410 {
1411 if (el_tools[i].readlibrary != 0)
1412 {
1413 for(j=0; j<io_libraryannouncecount; j++)
1414 (*el_tools[i].readlibrary)(io_libraryannounce[j]);
1415 }
1416 }
1417 return(0);
1418 }
1419 return(-1);
1420 }
1421
io_queuereadlibraryannouncement(LIBRARY * lib)1422 void io_queuereadlibraryannouncement(LIBRARY *lib)
1423 {
1424 REGISTER INTBIG i, newtotal;
1425 REGISTER LIBRARY **newlist;
1426
1427 if (io_libraryannouncecount >= io_libraryannouncetotal)
1428 {
1429 newtotal = io_libraryannouncetotal * 2;
1430 if (io_libraryannouncecount >= newtotal)
1431 newtotal = io_libraryannouncecount + 5;
1432 newlist = (LIBRARY **)emalloc(newtotal * (sizeof (LIBRARY *)), io_tool->cluster);
1433 if (newlist == 0) return;
1434 for(i=0; i<io_libraryannouncecount; i++)
1435 newlist[i] = io_libraryannounce[i];
1436 if (io_libraryannouncetotal > 0)
1437 efree((CHAR *)io_libraryannounce);
1438 io_libraryannounce = newlist;
1439 io_libraryannouncetotal = newtotal;
1440 }
1441 io_libraryannounce[io_libraryannouncecount++] = lib;
1442 }
1443
1444 /******************************* BLOATING *******************************/
1445
1446 /*
1447 * routine to indicate that CIF layer "layer" is to be bloated by "amount"
1448 */
io_setoutputbloat(CHAR * layer,INTBIG amount)1449 void io_setoutputbloat(CHAR *layer, INTBIG amount)
1450 {
1451 REGISTER BLOAT *bl;
1452
1453 /* special case when bloating the null layer */
1454 if (*layer == 0)
1455 {
1456 for(bl = io_curbloat; bl != NOBLOAT; bl = bl->nextbloat)
1457 ttyputmsg(M_("Bloating layer %s by %ld %ss"), bl->layer, bl->amount, unitsname(el_units));
1458 return;
1459 }
1460
1461 /* first see if this layer is already being bloated */
1462 for(bl = io_curbloat; bl != NOBLOAT; bl = bl->nextbloat)
1463 if (namesame(bl->layer, layer) == 0)
1464 {
1465 if (bl->amount == amount)
1466 {
1467 ttyputmsg(M_("Layer %s is already being bloated by %ld %ss"),
1468 bl->layer, amount, unitsname(el_units));
1469 return;
1470 }
1471 ttyputmsg(M_("Layer %s was being bloated by %ld %ss, now by %ld"),
1472 bl->layer, bl->amount, unitsname(el_units), amount);
1473 bl->amount = amount;
1474 return;
1475 }
1476
1477 bl = (BLOAT *)emalloc(sizeof (BLOAT), io_tool->cluster);
1478 if (bl == 0)
1479 {
1480 ttyputnomemory();
1481 return;
1482 }
1483 (void)allocstring(&bl->layer, layer, io_tool->cluster);
1484 bl->amount = amount;
1485 bl->nextbloat = io_curbloat;
1486 io_curbloat = bl;
1487 ttyputmsg(M_("Layer %s will be bloated by %ld %ss"), layer, amount, unitsname(el_units));
1488 }
1489
1490 /*
1491 * routine to tell the amount to bloat layer "lay"
1492 */
io_getoutputbloat(CHAR * layer)1493 INTBIG io_getoutputbloat(CHAR *layer)
1494 {
1495 REGISTER BLOAT *bl;
1496
1497 for(bl = io_curbloat; bl != NOBLOAT; bl = bl->nextbloat)
1498 if (namesame(bl->layer, layer) == 0) return(bl->amount);
1499 return(0);
1500 }
1501
1502 /******************************* LIBRARY REPAIR *******************************/
1503
1504 #define OLDSOURCEDCV 0 /* Source is DC Voltage */
1505 #define OLDSOURCEAC 0400000 /* Source is AC analysis */
1506 #define OLDSOURCEBULK 01000000 /* Source is Bulk */
1507 #define OLDSOURCEDCC 01400000 /* Source is DC Current */
1508 #define OLDSOURCECURMTR 02000000 /* Source is Current meter */
1509 #define OLDSOURCENODE 02400000 /* Source is Nodeset */
1510 #define OLDSOURCESPEC 03000000 /* Source is Special */
1511 #define OLDSOURCETRAN 03400000 /* Source is Transient Analysis */
1512 #define OLDSOURCEDCAN 04000000 /* Source is DC Analysis */
1513 #define OLDSOURCEEXT 04400000 /* Source is Extension */
1514
1515 /*
1516 * routine to complete formation of library "lib" that has just been read from
1517 * disk. Some data is not read, but computed from other data.
1518 */
io_fixnewlib(LIBRARY * lib,void * dia)1519 void io_fixnewlib(LIBRARY *lib, void *dia)
1520 {
1521 REGISTER NODEPROTO *np, *pnt, *onp;
1522 REGISTER NODEINST *ni, *newni;
1523 REGISTER ARCINST *ai;
1524 REGISTER LIBRARY *olib;
1525 REGISTER BOOLEAN first, changed;
1526 REGISTER INTBIG libunits, i, j, lam, oldtype, size, len, lambda,
1527 celllambda, totlx, tothx, totly, tothy, numchanged, *intkey;
1528 INTBIG lx, ly, hx, hy, major, minor, detail, type, addr, xoff, yoff, growx, growy,
1529 shiftx, shifty;
1530 UINTBIG olddescript[TEXTDESCRIPTSIZE];
1531 REGISTER CHAR *str, *pt, **newlist;
1532 float value;
1533 XARRAY trans;
1534 static POLYGON *poly = NOPOLYGON;
1535 static INTBIG sch_flipfloptypekey = 0;
1536 static INTBIG sch_transistortypekey = 0;
1537 static INTBIG sch_sourcekey = 0;
1538 static INTBIG sch_twoportkey = 0;
1539 CHAR line[200], *par[4], *newname;
1540 REGISTER VARIABLE *var, *newvar;
1541 REGISTER TECHNOLOGY *tech;
1542 REGISTER PORTPROTO *pp, *inpp;
1543 REGISTER PORTARCINST *pi;
1544 REGISTER PORTEXPINST *pe;
1545 extern ARCPROTO **gen_upconn;
1546 REGISTER void *infstr;
1547
1548 /* make sure units are correct */
1549 libunits = ((lib->userbits & LIBUNITS) >> LIBUNITSSH) << INTERNALUNITSSH;
1550 if ((libunits & INTERNALUNITS) != (el_units & INTERNALUNITS))
1551 {
1552 ttyputmsg(_("Converting library from %s units to %s units"), unitsname(libunits),
1553 unitsname(el_units));
1554 changeinternalunits(lib, libunits, el_units);
1555 }
1556
1557 /* check validity of instances */
1558 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1559 {
1560 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1561 if (olib == np->lib) break;
1562 if (olib == NOLIBRARY)
1563 {
1564 ttyputerr(_("ERROR: Cell %s: has invalid cell structure"), describenodeproto(np));
1565 continue;
1566 }
1567 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1568 {
1569 if (ni->proto->primindex != 0) continue;
1570 olib = ni->proto->lib;
1571 if (olib == lib) continue;
1572 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1573 if (olib == ni->proto->lib) break;
1574 if (olib == NOLIBRARY)
1575 {
1576 ttyputerr(_("ERROR: Cell %s: has instance from invalid library"), describenodeproto(np));
1577 ni->proto = gen_univpinprim;
1578 continue;
1579 }
1580 for(onp = olib->firstnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
1581 if (onp == ni->proto) break;
1582 if (onp == NONODEPROTO)
1583 {
1584 ttyputerr(_("ERROR: Cell %s: has instance with invalid prototype"), describenodeproto(np));
1585 ni->proto = gen_univpinprim;
1586 continue;
1587 }
1588 }
1589 }
1590
1591 /* create name hash table */
1592 db_buildnodeprotohashtable(lib);
1593
1594 /* create port name hash tables */
1595 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1596 db_buildportprotohashtable(np);
1597
1598 /* adjust every cell in the library */
1599 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1600 {
1601 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1602 for(pe = pp->subnodeinst->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
1603 if (pe->proto == pp->subportproto)
1604 {
1605 pp->subportexpinst = pe; break;
1606 }
1607 #ifdef MACOS
1608 /*
1609 * The Macintosh uses a different date epoch than other machines, and this
1610 * is handled in "dbtext.c". However, the adjustment code is recent,
1611 * and some old Macintosh libraries may have incorrect date information.
1612 *
1613 * The Macintosh epoch is 1904, but every other machine uses 1970.
1614 * Therefore, the Macintosh numbers are 66 years larger.
1615 *
1616 * To check for bogus date information, see if the date is larger
1617 * than the constant 0x9FE3EB1F. This constant is 1989 in Mac time
1618 * but is 2055 elsewhere (1989 is the earliest possible incarnation
1619 * of Electric on the Mac). If the date is that large, then either it
1620 * is 2055 and Macs still exist (unlikely) or the date is bad and needs
1621 * to have 66 years (0x7C254E10) subtracted from it.
1622 */
1623 if (np->creationdate > 0x9FE3EB1F) np->creationdate -= 0x7C254E10;
1624 if (np->revisiondate > 0x9FE3EB1F) np->revisiondate -= 0x7C254E10;
1625 #endif
1626 }
1627
1628 /* look for arrayed node specifications */
1629 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1630 {
1631 if (!isschematicview(np)) continue;
1632 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1633 {
1634 net_setnodewidth(ni);
1635 }
1636 }
1637
1638 /*
1639 * see if this is version 4 or earlier...
1640 * In version 4 and earlier, the basic unit was the centimicron and rotation
1641 * was specified in degrees. From version 5 and up, the basic unit is scaled
1642 * by 20 to the half-nanometer and the rotation fields are scaled by 10 to
1643 * tenth-degrees. Also, must convert some variable names.
1644 */
1645 io_getversion(lib, &major, &minor, &detail);
1646
1647 /* this is only done after all libraries are read */
1648 if (io_libinputrecursivedepth == 0)
1649 {
1650 /* now fill in the connection lists on the ports */
1651 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1652 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1653 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1654 {
1655 inpp = pp;
1656 for(;;)
1657 {
1658 if (inpp == NOPORTPROTO) break;
1659 if (inpp->parent->primindex != 0) break;
1660 inpp = inpp->subportproto;
1661 }
1662 if (inpp != NOPORTPROTO)
1663 pp->connects = inpp->connects;
1664 if (pp->connects == 0)
1665 {
1666 if (gen_upconn[0] != 0) pp->connects = gen_upconn; else
1667 pp->connects = &gen_upconn[1];
1668 pp->subportproto = pp->subnodeinst->proto->firstportproto;
1669 }
1670 }
1671
1672 /* rebuild list of node instances */
1673 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
1674 for(np = tech->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1675 np->firstinst = NONODEINST;
1676 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1677 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1678 np->firstinst = NONODEINST;
1679 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1680 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1681 {
1682 /* examine every nodeinst in the cell */
1683 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1684 {
1685 /* compute linked list of node instances */
1686 pnt = ni->proto;
1687 if (pnt == NONODEPROTO)
1688 {
1689 ttyputerr(_("Cell %s: has a node without a prototype"), describenodeproto(np));
1690 ni->proto = gen_univpinprim;
1691 }
1692 if (pnt->firstinst != NONODEINST) pnt->firstinst->previnst = ni;
1693 ni->nextinst = pnt->firstinst;
1694 ni->previnst = NONODEINST;
1695 pnt->firstinst = ni;
1696 }
1697 }
1698
1699 /* for versions 8.00 or later, look for arcs with negation in other "head" bit */
1700 if (major >= 8)
1701 {
1702 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1703 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1704 {
1705 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1706 {
1707 if ((ai->userbits&ISHEADNEGATED) != 0)
1708 {
1709 if ((ai->userbits&ISNEGATED) != 0)
1710 {
1711 ttyputmsg("Cell %s, arc %s is negated at both ends which is unsupported in this version of Electric. Ignoring head negation.",
1712 describenodeproto(np), describearcinst(ai));
1713 } else
1714 {
1715 /* only the head is negated: reverse the arc */
1716 if ((ai->userbits&REVERSEEND) != 0)
1717 ai->userbits &= ~REVERSEEND; else
1718 ai->userbits |= REVERSEEND;
1719 ai->userbits |= ISNEGATED;
1720 ai->userbits &= ~ISHEADNEGATED;
1721 }
1722 }
1723 }
1724 }
1725 }
1726
1727 /* for versions before 6.05bc, look for icon cells that are wrong */
1728 if (major < 6 ||
1729 (major == 6 && minor < 5) ||
1730 (major == 6 && minor == 5 && detail < 55))
1731 {
1732 numchanged = 0;
1733 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
1734 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1735 {
1736 first = TRUE;
1737 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1738 {
1739 boundobj(ni->geom, &lx, &hx, &ly, &hy);
1740 if (first)
1741 {
1742 first = FALSE;
1743 totlx = lx; tothx = hx;
1744 totly = ly; tothy = hy;
1745 } else
1746 {
1747 if (lx < totlx) totlx = lx;
1748 if (hx > tothx) tothx = hx;
1749 if (ly < totly) totly = ly;
1750 if (hy > tothy) tothy = hy;
1751 }
1752 }
1753 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1754 {
1755 boundobj(ai->geom, &lx, &hx, &ly, &hy);
1756 if (lx < totlx) totlx = lx;
1757 if (hx > tothx) tothx = hx;
1758 if (ly < totly) totly = ly;
1759 if (hy > tothy) tothy = hy;
1760 }
1761 if (first) continue;
1762 if (np->lowx == totlx && np->highx == tothx &&
1763 np->lowy == totly && np->highy == tothy) continue;
1764
1765 for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
1766 {
1767 growx = ((tothx - np->highx) + (totlx - np->lowx)) / 2;
1768 growy = ((tothy - np->highy) + (totly - np->lowy)) / 2;
1769 if (ni->transpose != 0)
1770 {
1771 makeangle(ni->rotation, ni->transpose, trans);
1772 } else
1773 {
1774 makeangle((3600 - ni->rotation)%3600, 0, trans);
1775 }
1776 xform(growx, growy, &shiftx, &shifty, trans);
1777 ni->lowx += totlx - np->lowx - growx + shiftx;
1778 ni->highx += tothx - np->highx - growx + shiftx;
1779 ni->lowy += totly - np->lowy - growy + shifty;
1780 ni->highy += tothy - np->highy - growy + shifty;
1781 updategeom(ni->geom, ni->parent);
1782 }
1783 np->lowx = totlx; np->highx = tothx;
1784 np->lowy = totly; np->highy = tothy;
1785 numchanged++;
1786 }
1787 if (numchanged != 0)
1788 {
1789 ttyputmsg(_("WARNING: due to changes in bounds calculation, %ld cell sizes were adjusted"),
1790 numchanged);
1791 ttyputmsg(_("...should do Check&Repair library"));
1792 }
1793 }
1794
1795 /* create network information */
1796 if (dia != 0) DiaSetTextProgress(dia, _("Building network data..."));
1797 if (io_libinputreadmany > 0)
1798 {
1799 /* many libraries read: renumber everything */
1800 (void)asktool(net_tool, x_("total-re-number"));
1801 } else
1802 {
1803 /* just 1 library read: renumber it */
1804 (void)asktool(net_tool, x_("library-re-number"), (INTBIG)lib);
1805 }
1806 }
1807
1808 /* set the cell's technology */
1809 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1810 np->tech = whattech(np);
1811
1812 /* check for incorrect layer counts on stored variables */
1813 io_fixtechlayers(lib);
1814
1815 /* for versions 7.01 or later, convert floating-point outline information */
1816 if (major >= 7 || (major == 7 && minor >= 1))
1817 {
1818 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1819 {
1820 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1821 {
1822 var = getvalkey((INTBIG)ni, VNODEINST, VFLOAT|VISARRAY, el_trace_key);
1823 if (var == NOVARIABLE) continue;
1824 len = getlength(var);
1825 intkey = (INTBIG *)emalloc(len*SIZEOFINTBIG, el_tempcluster);
1826 lambda = lambdaofnode(ni);
1827 for(i=0; i<len; i++)
1828 {
1829 intkey[i] = (int)(((float *)var->addr)[i] * lambda);
1830 }
1831 setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)intkey,
1832 VINTEGER|VISARRAY|(len<<VLENGTHSH));
1833 }
1834 }
1835 }
1836
1837 /* for versions 6.02 or earlier, convert text sizes */
1838 if (major < 6 || (major == 6 && minor <= 2))
1839 {
1840 #ifdef REPORTCONVERSION
1841 ttyputmsg(x_(" Converting text sizes"));
1842 #endif
1843 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1844 {
1845 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1846 {
1847 io_convertallrelativetext(ni->numvar, ni->firstvar);
1848 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1849 io_convertallrelativetext(pi->numvar, pi->firstvar);
1850 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
1851 io_convertallrelativetext(pe->numvar, pe->firstvar);
1852 if (ni->proto->primindex == 0)
1853 io_convertrelativetext(ni->textdescript);
1854 }
1855 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
1856 io_convertallrelativetext(ai->numvar, ai->firstvar);
1857 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1858 {
1859 io_convertallrelativetext(pp->numvar, pp->firstvar);
1860 io_convertrelativetext(pp->textdescript);
1861 }
1862 io_convertallrelativetext(np->numvar, np->firstvar);
1863 }
1864 io_convertallrelativetext(lib->numvar, lib->firstvar);
1865 }
1866
1867 /* for versions before 6.04c, convert text descriptor values */
1868 if (major < 6 ||
1869 (major == 6 && minor < 4) ||
1870 (major == 6 && minor == 4 && detail < 3))
1871 {
1872 #ifdef REPORTCONVERSION
1873 ttyputmsg(x_(" Converting text descriptors"));
1874 #endif
1875 io_converteverytextdescriptor(lib, 0);
1876 }
1877
1878 /* for versions before 6.03r, convert variables on schematic primitives */
1879 if (major < 6 ||
1880 (major == 6 && minor < 3) ||
1881 (major == 6 && minor == 3 && detail < 18))
1882 {
1883 if (sch_transistortypekey == 0)
1884 sch_transistortypekey = makekey(x_("SCHEM_transistor_type"));
1885 if (sch_sourcekey == 0)
1886 sch_sourcekey = makekey(x_("SCHEM_source"));
1887 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1888 {
1889 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1890 {
1891 if (ni->proto->primindex == 0) continue;
1892 if (ni->proto->tech == sch_tech)
1893 {
1894 if (ni->proto == sch_transistorprim)
1895 {
1896 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_transistortypekey);
1897 if (var != NOVARIABLE)
1898 {
1899 str = (CHAR *)var->addr;
1900 if (namesamen(str, x_("nmos"), 4) == 0)
1901 {
1902 ni->userbits |= TRANNMOS; str += 4;
1903 } else if (namesamen(str, x_("dmos"), 4) == 0)
1904 {
1905 ni->userbits |= TRANDMOS; str += 4;
1906 } else if (namesamen(str, x_("pmos"), 4) == 0)
1907 {
1908 ni->userbits |= TRANPMOS; str += 4;
1909 } else if (namesamen(str, x_("npn"), 3) == 0)
1910 {
1911 ni->userbits |= TRANNPN; str += 3;
1912 } else if (namesamen(str, x_("pnp"), 3) == 0)
1913 {
1914 ni->userbits |= TRANPNP; str += 3;
1915 } else if (namesamen(str, x_("njfet"), 5) == 0)
1916 {
1917 ni->userbits |= TRANNJFET; str += 5;
1918 } else if (namesamen(str, x_("pjfet"), 5) == 0)
1919 {
1920 ni->userbits |= TRANPJFET; str += 5;
1921 } else if (namesamen(str, x_("dmes"), 4) == 0)
1922 {
1923 ni->userbits |= TRANDMES; str += 4;
1924 } else if (namesamen(str, x_("emes"), 4) == 0)
1925 {
1926 ni->userbits |= TRANEMES; str += 4;
1927 }
1928 if (*str == 0) (void)delvalkey((INTBIG)ni, VNODEINST, sch_transistortypekey); else
1929 {
1930 TDCOPY(olddescript, var->textdescript);
1931 infstr = initinfstr();
1932 addstringtoinfstr(infstr, str);
1933 allocstring(&newname, returninfstr(infstr), el_tempcluster);
1934 var = setvalkey((INTBIG)ni, VNODEINST, sch_transistortypekey,
1935 (INTBIG)newname, var->type);
1936 efree(newname);
1937 if (var != NOVARIABLE)
1938 TDCOPY(var->textdescript, olddescript);
1939 }
1940 }
1941 } else if (ni->proto == sch_sourceprim)
1942 {
1943 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_sourcekey);
1944 if (var != NOVARIABLE)
1945 {
1946 str = (CHAR *)var->addr;
1947 if (namesamen(str, x_("vd"), 2) == 0)
1948 {
1949 ni->userbits |= OLDSOURCEDCAN; str += 2;
1950 } else if (namesamen(str, x_("v"), 1) == 0)
1951 {
1952 ni->userbits |= OLDSOURCEDCV; str++;
1953 } else if (namesamen(str, x_("cm"), 2) == 0)
1954 {
1955 ni->userbits |= OLDSOURCECURMTR; str += 2;
1956 } else if (namesamen(str, x_("c"), 1) == 0)
1957 {
1958 ni->userbits |= OLDSOURCEDCC; str++;
1959 } else if (namesamen(str, x_("t"), 1) == 0)
1960 {
1961 ni->userbits |= OLDSOURCETRAN; str++;
1962 } else if (namesamen(str, x_("a"), 1) == 0)
1963 {
1964 ni->userbits |= OLDSOURCEAC; str++;
1965 } else if (namesamen(str, x_("n"), 1) == 0)
1966 {
1967 ni->userbits |= OLDSOURCENODE; str++;
1968 } else if (namesamen(str, x_("x"), 1) == 0)
1969 {
1970 ni->userbits |= OLDSOURCEEXT; str++;
1971 } else if (namesamen(str, x_("b"), 1) == 0)
1972 {
1973 ni->userbits |= OLDSOURCEBULK; str++;
1974 } else if (namesamen(str, x_("s"), 1) == 0)
1975 {
1976 ni->userbits |= OLDSOURCESPEC; str++;
1977 }
1978 if (*str == '/') str++;
1979 if (*str == 0) (void)delvalkey((INTBIG)ni, VNODEINST, sch_sourcekey); else
1980 {
1981 TDCOPY(olddescript, var->textdescript);
1982 infstr = initinfstr();
1983 addstringtoinfstr(infstr, str);
1984 allocstring(&newname, returninfstr(infstr), el_tempcluster);
1985 var = setvalkey((INTBIG)ni, VNODEINST, sch_sourcekey,
1986 (INTBIG)newname, var->type|VDISPLAY);
1987 efree(newname);
1988 if (var != NOVARIABLE)
1989 TDCOPY(var->textdescript, olddescript);
1990 }
1991 }
1992 } else if (ni->proto == sch_diodeprim)
1993 {
1994 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_diodekey);
1995 if (var != NOVARIABLE)
1996 {
1997 str = (CHAR *)var->addr;
1998 while (*str == ' ' || *str == '\t') str++;
1999 if (tolower(*str) == 'z')
2000 {
2001 str++;
2002 ni->userbits |= DIODEZENER;
2003 }
2004 if (*str == 0) (void)delvalkey((INTBIG)ni, VNODEINST, sch_diodekey); else
2005 {
2006 TDCOPY(olddescript, var->textdescript);
2007 infstr = initinfstr();
2008 addstringtoinfstr(infstr, str);
2009 allocstring(&newname, returninfstr(infstr), el_tempcluster);
2010 var = setvalkey((INTBIG)ni, VNODEINST, sch_diodekey,
2011 (INTBIG)newname, var->type|VDISPLAY);
2012 efree(newname);
2013 if (var != NOVARIABLE)
2014 TDCOPY(var->textdescript, olddescript);
2015 }
2016 }
2017 } else if (ni->proto == sch_capacitorprim)
2018 {
2019 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_capacitancekey);
2020 if (var != NOVARIABLE)
2021 {
2022 str = (CHAR *)var->addr;
2023 while (*str == ' ' || *str == '\t') str++;
2024 if (tolower(*str) == 'e')
2025 {
2026 str++;
2027 ni->userbits |= CAPACELEC;
2028 }
2029 if (*str == 0) (void)delvalkey((INTBIG)ni, VNODEINST, sch_capacitancekey); else
2030 {
2031 TDCOPY(olddescript, var->textdescript);
2032 infstr = initinfstr();
2033 addstringtoinfstr(infstr, str);
2034 allocstring(&newname, returninfstr(infstr), el_tempcluster);
2035 var = setvalkey((INTBIG)ni, VNODEINST, sch_capacitancekey,
2036 (INTBIG)newname, var->type|VDISPLAY);
2037 efree(newname);
2038 if (var != NOVARIABLE)
2039 TDCOPY(var->textdescript, olddescript);
2040 }
2041 }
2042 } else if (ni->proto == sch_twoportprim)
2043 {
2044 if (sch_twoportkey == 0)
2045 sch_twoportkey = makekey(x_("SCHEM_twoport_type"));
2046 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_twoportkey);
2047 if (var != NOVARIABLE)
2048 {
2049 str = (CHAR *)var->addr;
2050 while (*str == ' ') str++;
2051 switch (tolower(*str))
2052 {
2053 case 'u': ni->userbits |= TWOPVCVS; str++; break;
2054 case 'g': ni->userbits |= TWOPVCCS; str++; break;
2055 case 'h': ni->userbits |= TWOPCCVS; str++; break;
2056 case 'f': ni->userbits |= TWOPCCCS; str++; break;
2057 case 'l': ni->userbits |= TWOPTLINE; str++; break;
2058 }
2059 nextchangequiet();
2060 if (*str == 0) (void)delvalkey((INTBIG)ni, VNODEINST, sch_twoportkey); else
2061 {
2062 TDCOPY(olddescript, var->textdescript);
2063 infstr = initinfstr();
2064 addstringtoinfstr(infstr, str);
2065 allocstring(&newname, returninfstr(infstr), el_tempcluster);
2066 var = setvalkey((INTBIG)ni, VNODEINST, sch_spicemodelkey,
2067 (INTBIG)newname, var->type|VDISPLAY);
2068 efree(newname);
2069 if (var != NOVARIABLE)
2070 TDCOPY(var->textdescript, olddescript);
2071 }
2072 }
2073 } else if (ni->proto == sch_ffprim)
2074 {
2075 if (sch_flipfloptypekey == 0)
2076 sch_flipfloptypekey = makekey(x_("SCHEM_flipflop_type"));
2077 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_flipfloptypekey);
2078 if (var != NOVARIABLE)
2079 {
2080 for (str = (CHAR *)var->addr; *str != 0; str++)
2081 {
2082 if (namesamen(str, x_("rs"), 2) == 0)
2083 {
2084 ni->userbits |= FFTYPERS;
2085 str++;
2086 continue;
2087 }
2088 if (namesamen(str, x_("jk"), 2) == 0)
2089 {
2090 ni->userbits |= FFTYPEJK;
2091 str++;
2092 continue;
2093 }
2094 if (namesamen(str, x_("t"), 1) == 0)
2095 {
2096 ni->userbits |= FFTYPET;
2097 continue;
2098 }
2099 if (namesamen(str, x_("d"), 1) == 0)
2100 {
2101 ni->userbits |= FFTYPED;
2102 continue;
2103 }
2104 if (namesamen(str, x_("ms"), 2) == 0)
2105 {
2106 ni->userbits |= FFCLOCKMS;
2107 str++;
2108 continue;
2109 }
2110 if (namesamen(str, x_("p"), 1) == 0)
2111 {
2112 ni->userbits |= FFCLOCKP;
2113 continue;
2114 }
2115 if (namesamen(str, x_("n"), 1) == 0)
2116 {
2117 ni->userbits |= FFCLOCKN;
2118 continue;
2119 }
2120 }
2121 nextchangequiet();
2122 (void)delvalkey((INTBIG)ni, VNODEINST, sch_flipfloptypekey);
2123 }
2124 }
2125 }
2126 }
2127 }
2128 }
2129
2130 /* for versions before 6.05bh, make sure that "far text" bit is set right */
2131 if (io_libinputrecursivedepth == 0)
2132 {
2133 if (major < 6 ||
2134 (major == 6 && minor < 5) ||
2135 (major == 6 && minor == 5 && detail < 60))
2136 {
2137 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
2138 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2139 {
2140 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2141 us_computenodefartextbit(ni);
2142 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
2143 us_computearcfartextbit(ai);
2144 }
2145 }
2146 }
2147
2148 /* for versions before 6.05bi, make all cell centers be "visible only inside cell" */
2149 if (major < 6 ||
2150 (major == 6 && minor < 5) ||
2151 (major == 6 && minor == 5 && detail < 61))
2152 {
2153 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2154 {
2155 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2156 {
2157 if (ni->proto != gen_cellcenterprim) continue;
2158 ni->userbits |= NVISIBLEINSIDE;
2159 }
2160 }
2161 }
2162
2163 /* for versions before 6.05ba, convert source nodes */
2164 if (major < 6 ||
2165 (major == 6 && minor < 5) ||
2166 (major == 6 && minor == 5 && detail < 53))
2167 {
2168 /* change all Wire_Pins that are 1x1 to be 0.5x0.5 */
2169 numchanged = 0;
2170 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2171 {
2172 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2173 {
2174 if (ni->proto->primindex == 0) continue;
2175 if (ni->proto->tech != sch_tech) continue;
2176 if (ni->proto != sch_wirepinprim) continue;
2177 lambda = lambdaofnode(ni);
2178 if (ni->highx - ni->lowx == lambda &&
2179 ni->highy - ni->lowy == lambda)
2180 {
2181 modifynodeinst(ni, lambda/4, lambda/4, -lambda/4, -lambda/4, 0, 0);
2182 numchanged++;
2183 }
2184 }
2185 }
2186 if (numchanged != 0)
2187 ttyputmsg(_("Note: reduced the size of %ld schematic wire pins from 1x1 to 0.5x0.5"),
2188 numchanged);
2189 }
2190
2191 /* for versions before 6.05al, convert source nodes */
2192 if (major < 6 ||
2193 (major == 6 && minor < 5) ||
2194 (major == 6 && minor == 5 && detail < 38))
2195 {
2196 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2197 {
2198 changed = FALSE;
2199 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2200 {
2201 if (ni->proto->primindex == 0) continue;
2202 if (ni->proto->tech != sch_tech) continue;
2203 if (ni->proto != sch_sourceprim) continue;
2204 str = 0;
2205 switch (ni->userbits&NTECHBITS)
2206 {
2207 case OLDSOURCEDCAN: str = x_("AnalysisDC"); break;
2208 case OLDSOURCEDCV: str = x_("DCVoltage"); break;
2209 case OLDSOURCEDCC: str = x_("DCCurrent"); break;
2210 case OLDSOURCETRAN: str = x_("AnalysisTransient"); break;
2211 case OLDSOURCEAC: str = x_("AnalysisAC"); break;
2212 case OLDSOURCENODE: str = x_("NodeSet"); break;
2213 case OLDSOURCEEXT: str = x_("Extension"); break;
2214 }
2215 if (str == 0) continue;
2216
2217 /* make sure the "spiceparts" library is read */
2218 olib = getlibrary(x_("spiceparts"));
2219 if (olib == NOLIBRARY)
2220 {
2221 par[0] = x_("library");
2222 par[1] = x_("read");
2223 par[2] = x_("spiceparts.txt");
2224 par[3] = x_("text");
2225 telltool(us_tool, 4, par);
2226 olib = getlibrary(x_("spiceparts"));
2227 if (olib == NOLIBRARY)
2228 {
2229 ttyputerr(_("Cannot find spice parts library for source conversion"));
2230 break;
2231 }
2232 }
2233 esnprintf(line, 200, x_("spiceparts:%s"), str);
2234 onp = getnodeproto(line);
2235 if (onp == NONODEPROTO)
2236 {
2237 ttyputerr(_("Cannot find '%s' for source conversion"), line);
2238 break;
2239 }
2240 newni = replacenodeinst(ni, onp, TRUE, TRUE);
2241 if (newni != NONODEINST)
2242 newni->userbits |= NEXPAND;
2243 changed = TRUE;
2244 }
2245 if (ni != NONODEINST) break;
2246 if (changed)
2247 ttyputmsg(_("Warning: SPICE components converted in cell %s. Additional editing may be required."),
2248 describenodeproto(np));
2249 }
2250 }
2251
2252 /* for versions before 6.07ap, make parameters visible by default */
2253 if (major < 6 ||
2254 (major == 6 && minor < 7) ||
2255 (major == 6 && minor == 7 && detail < 26+16))
2256 {
2257 j = 0;
2258 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2259 {
2260 for(i=0; i<np->numvar; i++)
2261 {
2262 var = &np->firstvar[i];
2263 if (TDGETISPARAM(var->textdescript) == 0) continue;
2264 if (TDGETINTERIOR(var->textdescript) == 0) continue;
2265 TDSETINTERIOR(var->textdescript, 0);
2266 j++;
2267 }
2268 }
2269 if (j > 0)
2270 {
2271 ttyputmsg(x_("Library %s: cleaned up %ld old parameter visibility settings"),
2272 lib->libname, j);
2273 lib->userbits |= LIBCHANGEDMINOR;
2274 }
2275 }
2276
2277 /* for versions before 6.07b, adjust text */
2278 if (major < 6 ||
2279 (major == 6 && minor < 7) ||
2280 (major == 6 && minor == 7 && detail < 2))
2281 {
2282 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2283 {
2284 tech = np->tech;
2285 if (tech == NOTECHNOLOGY) tech = whattech(np);
2286 celllambda = lib->lambda[tech->techindex];
2287 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2288 {
2289 onp = ni->proto;
2290 tech = onp->tech;
2291 if (tech == NOTECHNOLOGY) tech = whattech(onp);
2292 lambda = lib->lambda[tech->techindex];
2293 if (lambda == celllambda) continue;
2294 for(i=0; i<ni->numvar; i++)
2295 {
2296 var = &ni->firstvar[i];
2297 if ((var->type & VDISPLAY) == 0) continue;
2298 xoff = muldiv(TDGETXOFF(var->textdescript), lambda, celllambda);
2299 yoff = muldiv(TDGETYOFF(var->textdescript), lambda, celllambda);
2300 TDSETOFF(var->textdescript, xoff, yoff);
2301 }
2302 us_computenodefartextbit(ni);
2303 }
2304 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
2305 {
2306 tech = ai->proto->tech;
2307 lambda = lib->lambda[tech->techindex];
2308 if (lambda == celllambda) continue;
2309 for(i=0; i<ai->numvar; i++)
2310 {
2311 var = &ai->firstvar[i];
2312 if ((var->type & VDISPLAY) == 0) continue;
2313 xoff = muldiv(TDGETXOFF(var->textdescript), lambda, celllambda);
2314 yoff = muldiv(TDGETYOFF(var->textdescript), lambda, celllambda);
2315 TDSETOFF(var->textdescript, xoff, yoff);
2316 }
2317 us_computearcfartextbit(ai);
2318 }
2319 }
2320 }
2321
2322 /* for versions before 6.04o, separate transistor size and SPICE info */
2323 if (major < 6 ||
2324 (major == 6 && minor < 4) ||
2325 (major == 6 && minor == 4 && detail < 15))
2326 {
2327 if (sch_transistortypekey == 0)
2328 sch_transistortypekey = makekey(x_("SCHEM_transistor_type"));
2329 if (sch_sourcekey == 0)
2330 sch_sourcekey = makekey(x_("SCHEM_source"));
2331 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2332 {
2333 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2334 {
2335 if (ni->proto->primindex == 0) continue;
2336 if (ni->proto->tech != sch_tech) continue;
2337
2338 /* convert "SCHEM_source" to "SIM_spice_model" */
2339 var = getvalkey((INTBIG)ni, VNODEINST, -1, sch_sourcekey);
2340 if (var != NOVARIABLE)
2341 {
2342 TDCOPY(olddescript, var->textdescript);
2343 newvar = setvalkey((INTBIG)ni, VNODEINST, sch_spicemodelkey, var->addr,
2344 var->type);
2345 if (newvar != 0)
2346 TDCOPY(newvar->textdescript, olddescript);
2347 (void)delvalkey((INTBIG)ni, VNODEINST, sch_sourcekey);
2348 }
2349
2350 if (ni->proto != sch_transistorprim &&
2351 ni->proto != sch_transistor4prim) continue;
2352 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, sch_transistortypekey);
2353 if (var == NOVARIABLE) continue;
2354
2355 /* look for "/" and split into Width and Length */
2356 str = (CHAR *)var->addr;
2357 oldtype = var->type;
2358 TDCOPY(olddescript, var->textdescript);
2359 for(pt = str; *pt != 0; pt++) if (*pt == '/') break;
2360 if (*pt == '/')
2361 {
2362 *pt++ = 0;
2363
2364 /* determine separation of descriptors */
2365 us_getlenwidoffset(ni, olddescript, &xoff, &yoff);
2366 getsimpletype(str, &type, &addr, 0);
2367 type |= oldtype & (VCODE1 | VCODE2 | VDISPLAY | VDONTSAVE);
2368 newvar = setvalkey((INTBIG)ni, VNODEINST, el_attrkey_width, addr, type);
2369 if (newvar != NOVARIABLE)
2370 {
2371 TDCOPY(newvar->textdescript, olddescript);
2372 TDSETOFF(newvar->textdescript, TDGETXOFF(newvar->textdescript)+xoff,
2373 TDGETYOFF(newvar->textdescript)+yoff);
2374 }
2375
2376 str = pt;
2377 for(pt = str; *pt != 0; pt++) if (*pt == '/') break;
2378 if (*pt == '/') *pt++ = 0;
2379 getsimpletype(str, &type, &addr, 0);
2380 type |= oldtype & (VCODE1 | VCODE2 | VDISPLAY | VDONTSAVE);
2381 newvar = setvalkey((INTBIG)ni, VNODEINST, el_attrkey_length, addr, type);
2382 if (newvar != NOVARIABLE)
2383 {
2384 TDCOPY(newvar->textdescript, olddescript);
2385 size = TDGETSIZE(newvar->textdescript);
2386 i = TXTGETPOINTS(size);
2387 if (i > 3) size = TXTSETPOINTS(i-2); else
2388 {
2389 i = TXTGETQLAMBDA(size);
2390 if (i > 3) size = TXTSETQLAMBDA(i-2);
2391 }
2392 TDSETSIZE(newvar->textdescript, size);
2393 TDSETOFF(newvar->textdescript, TDGETXOFF(newvar->textdescript)-xoff,
2394 TDGETYOFF(newvar->textdescript)-yoff);
2395 }
2396
2397 /* see if a SPICE model is at the end */
2398 if (*pt != 0)
2399 {
2400 type = VSTRING | (oldtype & (VCODE1 | VCODE2 | VDISPLAY | VDONTSAVE));
2401 newvar = setvalkey((INTBIG)ni, VNODEINST, sch_spicemodelkey,
2402 (INTBIG)pt, type);
2403 if (newvar != NOVARIABLE)
2404 TDCOPY(newvar->textdescript, olddescript);
2405 }
2406 } else
2407 {
2408 /* single number: just save Area */
2409 getsimpletype(str, &type, &addr, 0);
2410 type |= oldtype & (VCODE1 | VCODE2 | VDISPLAY | VDONTSAVE);
2411 newvar = setvalkey((INTBIG)ni, VNODEINST, el_attrkey_area, addr, type);
2412 if (newvar != NOVARIABLE)
2413 TDCOPY(newvar->textdescript, olddescript);
2414 }
2415 (void)delvalkey((INTBIG)ni, VNODEINST, sch_transistortypekey);
2416 }
2417 }
2418 }
2419
2420 /* for versions before 6.03g, convert schematic and mocmossub primitives */
2421 if (major < 6 ||
2422 (major == 6 && minor < 3) ||
2423 (major == 6 && minor == 3 && detail < 7))
2424 {
2425 #ifdef REPORTCONVERSION
2426 ttyputmsg(x_(" Converting schematic and MOSIS CMOS primitives"));
2427 #endif
2428 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2429 {
2430 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2431 {
2432 if (ni->proto->primindex == 0) continue;
2433 if (ni->proto->tech == sch_tech)
2434 {
2435 if (ni->proto == sch_pwrprim)
2436 {
2437 lam = lib->lambda[sch_tech->techindex];
2438 io_fixupnodeinst(ni, lam/2, lam/2, -lam/2, -lam/2);
2439 } else if (ni->proto == sch_gndprim)
2440 {
2441 lam = lib->lambda[sch_tech->techindex];
2442 io_fixupnodeinst(ni, lam/2, 0, -lam/2, 0);
2443 } else if (ni->proto == sch_capacitorprim)
2444 {
2445 lam = lib->lambda[sch_tech->techindex];
2446 io_fixupnodeinst(ni, lam/2, 0, -lam/2, 0);
2447 } else if (ni->proto == sch_resistorprim)
2448 {
2449 lam = lib->lambda[sch_tech->techindex];
2450 io_fixupnodeinst(ni, 0, lam/2, 0, -lam/2);
2451 }
2452 } else if (ni->proto->tech == mocmos_tech)
2453 {
2454 if (ni->proto == mocmos_metal1metal2prim)
2455 {
2456 lam = lib->lambda[mocmos_tech->techindex];
2457 io_fixupnodeinst(ni, -lam/2, -lam/2, lam/2, lam/2);
2458 } else if (ni->proto == mocmos_metal4metal5prim)
2459 {
2460 lam = lib->lambda[mocmos_tech->techindex];
2461 io_fixupnodeinst(ni, -lam/2, -lam/2, lam/2, lam/2);
2462 } else if (ni->proto == mocmos_metal5metal6prim)
2463 {
2464 lam = lib->lambda[mocmos_tech->techindex];
2465 io_fixupnodeinst(ni, -lam, -lam, lam, lam);
2466 } else if (ni->proto == mocmos_ptransistorprim)
2467 {
2468 lam = lib->lambda[mocmos_tech->techindex];
2469 io_fixupnodeinst(ni, 0, -lam, 0, lam);
2470 } else if (ni->proto == mocmos_ntransistorprim)
2471 {
2472 lam = lib->lambda[mocmos_tech->techindex];
2473 io_fixupnodeinst(ni, 0, -lam, 0, lam);
2474 } else if (ni->proto == mocmos_metal1poly2prim)
2475 {
2476 lam = lib->lambda[mocmos_tech->techindex];
2477 io_fixupnodeinst(ni, -lam*3, -lam*3, lam*3, lam*3);
2478 } else if (ni->proto == mocmos_metal1poly12prim)
2479 {
2480 lam = lib->lambda[mocmos_tech->techindex];
2481 io_fixupnodeinst(ni, -lam*4, -lam*4, lam*4, lam*4);
2482 }
2483 }
2484 }
2485 }
2486 }
2487
2488 /* for versions before 6.03l, convert mocmossub via4-via6 */
2489 if (major < 6 ||
2490 (major == 6 && minor < 3) ||
2491 (major == 6 && minor == 3 && detail < 12))
2492 {
2493 #ifdef REPORTCONVERSION
2494 ttyputmsg(x_(" Converting MOSIS CMOS vias"));
2495 #endif
2496 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2497 {
2498 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2499 {
2500 if (ni->proto->primindex == 0) continue;
2501 if (ni->proto->tech != mocmos_tech) continue;
2502 if (namesame(ni->proto->protoname, x_("Metal-3-Metal-4-Con")) == 0 ||
2503 namesame(ni->proto->protoname, x_("Metal-4-Metal-5-Con")) == 0 ||
2504 namesame(ni->proto->protoname, x_("Metal-5-Metal-6-Con")) == 0)
2505 {
2506 lam = lib->lambda[mocmos_tech->techindex];
2507 io_fixupnodeinst(ni, -lam, -lam, lam, lam);
2508 }
2509 }
2510 }
2511 }
2512
2513 /* for versions before 6.03aa, convert mocmossub well contacts */
2514 if (major < 6 ||
2515 (major == 6 && minor < 3) ||
2516 (major == 6 && minor == 3 && detail < 27))
2517 {
2518 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2519 {
2520 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2521 {
2522 if (ni->proto->primindex == 0) continue;
2523 if (ni->proto->tech != mocmos_tech) continue;
2524 if (namesame(ni->proto->protoname, x_("Metal-1-N-Well-Con")) == 0 ||
2525 namesame(ni->proto->protoname, x_("Metal-1-P-Well-Con")) == 0)
2526 {
2527 lam = lib->lambda[mocmos_tech->techindex];
2528 io_fixupnodeinst(ni, -lam-lam/2, -lam-lam/2, lam+lam/2, lam+lam/2);
2529 }
2530 }
2531 }
2532 }
2533
2534 /* for versions before 6.05ab, derive "far text" bits */
2535 if (major < 6 ||
2536 (major == 6 && minor < 5) ||
2537 (major == 6 && minor == 5 && detail < 28))
2538 {
2539 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2540 {
2541 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2542 us_computenodefartextbit(ni);
2543 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
2544 us_computearcfartextbit(ai);
2545 }
2546 }
2547
2548 /* for versions before 6.05ak, convert quick-key bindings */
2549 if (major < 6 ||
2550 (major == 6 && minor < 5) ||
2551 (major == 6 && minor == 5 && detail < 37))
2552 {
2553 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_quickkeyskey);
2554 if (var != NOVARIABLE)
2555 {
2556 len = getlength(var);
2557 newlist = (CHAR **)emalloc(len * (sizeof (CHAR *)), el_tempcluster);
2558 changed = FALSE;
2559 for(i=0; i<len; i++)
2560 {
2561 pt = ((CHAR **)var->addr)[i];
2562 (void)allocstring(&newlist[i], pt, el_tempcluster);
2563 if (pt[1] != '/') continue;
2564 j = pt[0] & 0xFF;
2565 if (j >= 0216 && j <= 0231)
2566 {
2567 /* convert former "function" key */
2568 esnprintf(line, 200, x_("F%ld%s"), j - 0215, &pt[1]);
2569 (void)reallocstring(&newlist[i], line, el_tempcluster);
2570 changed = TRUE;
2571 }
2572 }
2573 if (changed)
2574 {
2575 nextchangequiet();
2576 setvalkey((INTBIG)us_tool, VTOOL, us_quickkeyskey, (INTBIG)newlist,
2577 VSTRING|VISARRAY|(len<<VLENGTHSH));
2578 }
2579 for(i=0; i<len; i++) efree((CHAR *)newlist[i]);
2580 efree((CHAR *)newlist);
2581 }
2582 }
2583
2584 /* for versions before 6.06i, convert electrical units */
2585 if (major < 6 ||
2586 (major == 6 && minor < 6) ||
2587 (major == 6 && minor == 6 && detail < 9))
2588 {
2589 var = getvalkey((INTBIG)lib, VLIBRARY, VINTEGER, us_electricalunitskey);
2590 if (var != NOVARIABLE)
2591 {
2592 j = var->addr;
2593 i = (j&INTERNALCAPUNITS) >> INTERNALCAPUNITSSH;
2594 if (i >= INTCAPUNITNFARAD)
2595 {
2596 j = (j & ~INTERNALCAPUNITS) | ((i+1) << INTERNALCAPUNITSSH);
2597 nextchangequiet();
2598 setvalkey((INTBIG)lib, VLIBRARY, us_electricalunitskey, j, VINTEGER);
2599 us_electricalunits = j;
2600 }
2601 }
2602 if (j != us_electricalunits)
2603 io_converteverytextdescriptor(lib, 1);
2604 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2605 {
2606 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2607 {
2608 if (ni->proto == sch_resistorprim)
2609 {
2610 var = getvalkey((INTBIG)ni, VNODEINST, -1, sch_resistancekey);
2611 if (var != NOVARIABLE)
2612 {
2613 pt = describesimplevariable(var);
2614 value = (float)eatof(pt);
2615 i = estrlen(pt);
2616 if (i > 0)
2617 {
2618 if (tolower(pt[i-1]) == 'g')
2619 {
2620 value = value * 1000000000.0f;
2621 } else if (i > 2 && namesame(&pt[i-3], x_("meg")) == 0)
2622 {
2623 value = value * 1000000.0f;
2624 } else if (tolower(pt[i-1]) == 'k')
2625 {
2626 value = value * 1000.0f;
2627 }
2628 }
2629 var = setvalkey((INTBIG)ni, VNODEINST, sch_resistancekey,
2630 castint(value), VFLOAT | (var->type & ~VTYPE));
2631 if (var != NOVARIABLE)
2632 TDSETUNITS(var->textdescript, VTUNITSRES);
2633 }
2634 continue;
2635 }
2636 if (ni->proto == sch_capacitorprim)
2637 {
2638 var = getvalkey((INTBIG)ni, VNODEINST, -1, sch_capacitancekey);
2639 if (var != NOVARIABLE)
2640 {
2641 pt = describesimplevariable(var);
2642 value = (float)eatof(pt);
2643 i = estrlen(pt);
2644 if (i > 0)
2645 {
2646 if (tolower(pt[i-1]) == 'f')
2647 {
2648 value = value / 1000000000000000.0f;
2649 } else if (tolower(pt[i-1]) == 'p')
2650 {
2651 value = value / 1000000000000.0f;
2652 } else if (tolower(pt[i-1]) == 'u')
2653 {
2654 value = value / 1000000.0f;
2655 } else if (tolower(pt[i-1]) == 'm')
2656 {
2657 value = value / 1000.0f;
2658 }
2659 }
2660 var = setvalkey((INTBIG)ni, VNODEINST, sch_capacitancekey,
2661 castint(value), VFLOAT | (var->type & ~VTYPE));
2662 if (var != NOVARIABLE)
2663 TDSETUNITS(var->textdescript, VTUNITSCAP);
2664 }
2665 continue;
2666 }
2667 if (ni->proto == sch_inductorprim)
2668 {
2669 var = getvalkey((INTBIG)ni, VNODEINST, -1, sch_inductancekey);
2670 if (var != NOVARIABLE)
2671 {
2672 pt = describesimplevariable(var);
2673 value = (float)eatof(pt);
2674 i = estrlen(pt);
2675 if (i > 0)
2676 {
2677 if (tolower(pt[i-1]) == 'u')
2678 {
2679 value = value / 1000000.0f;
2680 } else if (tolower(pt[i-1]) == 'm')
2681 {
2682 value = value / 1000.0f;
2683 }
2684 }
2685 var = setvalkey((INTBIG)ni, VNODEINST, sch_inductancekey,
2686 castint(value), VFLOAT | (var->type & ~VTYPE));
2687 if (var != NOVARIABLE)
2688 TDSETUNITS(var->textdescript, VTUNITSIND);
2689 }
2690 continue;
2691 }
2692 }
2693 }
2694 }
2695
2696 /* for versions before 6.08, adjust ports in technology-edit libraries */
2697 if (major < 6 ||
2698 (major == 6 && minor < 8))
2699 {
2700 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2701 {
2702 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2703 {
2704 if (ni->proto == gen_portprim)
2705 modifynodeinst(ni, -4000, -4000, 4000, 4000, 0, 0);
2706 }
2707 }
2708 }
2709
2710 /* for versions before 6.08v, set "technology edit" bit for appropriate cells */
2711 if (major < 6 ||
2712 (major == 6 && minor < 8) ||
2713 (major == 6 && minor == 8 && detail < 22))
2714 {
2715 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2716 {
2717 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2718 {
2719 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
2720 if (var != NOVARIABLE) break;
2721 }
2722 if (ni != NONODEINST)
2723 np->userbits |= TECEDITCELL;
2724 }
2725 }
2726
2727 /* for versions before 7.00l, convert quick key bindings that refer to "facets" */
2728 if (major < 7 ||
2729 (major == 7 && minor < 0) ||
2730 (major == 7 && minor == 0 && detail < 12))
2731 {
2732 var = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_quickkeyskey);
2733 if (var != NOVARIABLE)
2734 {
2735 len = getlength(var);
2736 for(i=0; i<len; i++)
2737 {
2738 for(pt = ((CHAR **)var->addr)[i]; *pt != 0; pt++)
2739 {
2740 if (namesamen(pt, "facet", 5) != 0) continue;
2741 strcpy(pt, "Cell");
2742 strcpy(&pt[4], &pt[5]);
2743 }
2744 }
2745 }
2746 }
2747
2748 /* the rest of the changes are just for version 4 or earlier */
2749 if (major >= 5) return;
2750
2751 /* setup for units conversion */
2752 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
2753
2754 /* must scale, first make sure the technologies agree with this library */
2755 if (lib != el_curlib)
2756 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2757 changetechnologylambda(tech, lib->lambda[tech->techindex]);
2758
2759 /* now scale */
2760 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2761 {
2762 var = getvalkey((INTBIG)np, VNODEPROTO, VINTEGER|VISARRAY, el_prototype_center_key);
2763 if (var != NOVARIABLE)
2764 {
2765 ((INTBIG *)var->addr)[0] *= 20;
2766 ((INTBIG *)var->addr)[1] *= 20;
2767 }
2768 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2769 {
2770 ni->lowx *= 20; ni->highx *= 20;
2771 ni->lowy *= 20; ni->highy *= 20;
2772 ni->rotation *= 10;
2773 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, us_edtec_option_key);
2774 if (var != NOVARIABLE)
2775 {
2776 if (var->addr == TECHLAMBDA)
2777 {
2778 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, art_messagekey);
2779 if (var != NOVARIABLE)
2780 {
2781 lam = myatoi(&((CHAR *)var->addr)[8]);
2782 (void)esnprintf(line, 200, x_("Lambda: %ld"), lam*20);
2783 nextchangequiet();
2784 (void)setvalkey((INTBIG)ni, VNODEINST, art_messagekey,
2785 (INTBIG)line, VSTRING|VDISPLAY);
2786 }
2787 }
2788 }
2789 var = gettrace(ni);
2790 if (var != NOVARIABLE)
2791 {
2792 i = getlength(var);
2793 for(j=0; j<i; j++) ((INTBIG *)var->addr)[j] *= 20;
2794 }
2795 var = getvalkey((INTBIG)ni, VNODEINST, VINTEGER, art_degreeskey);
2796 if (var != NOVARIABLE) var->addr *= 10;
2797 boundobj(ni->geom, &ni->geom->lowx, &ni->geom->highx, &ni->geom->lowy, &ni->geom->highy);
2798 }
2799 }
2800
2801 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2802 {
2803 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
2804 {
2805 ai->width *= 20;
2806 ai->end[0].xpos *= 20; ai->end[0].ypos *= 20;
2807 ai->end[1].xpos *= 20; ai->end[1].ypos *= 20;
2808 (void)setshrinkvalue(ai, FALSE);
2809 var = getvalkey((INTBIG)ai, VARCINST, VINTEGER, el_arc_radius_key);
2810 if (var != NOVARIABLE) var->addr *= 20;
2811 for(i=0; i<2; i++)
2812 {
2813 /* make sure arcinst connects in portinst area */
2814 shapeportpoly(ai->end[i].nodeinst, ai->end[i].portarcinst->proto, poly, FALSE);
2815 if (isinside(ai->end[i].xpos, ai->end[i].ypos, poly)) continue;
2816 portposition(ai->end[i].nodeinst, ai->end[i].portarcinst->proto, &lx, &ly);
2817 if (lx == ai->end[i].xpos && ly == ai->end[i].ypos) continue;
2818
2819 /* try to make manhattan fix */
2820 if ((ai->end[0].xpos == ai->end[1].xpos) && isinside(ai->end[i].xpos, ly, poly))
2821 ai->end[i].ypos = ly; else
2822 if ((ai->end[0].ypos == ai->end[1].ypos) &&
2823 isinside(lx, ai->end[i].ypos, poly))
2824 ai->end[i].xpos = lx; else
2825 {
2826 ai->end[i].xpos = lx; ai->end[i].ypos = ly;
2827 }
2828 }
2829 ai->length = computedistance(ai->end[0].xpos,ai->end[0].ypos,
2830 ai->end[1].xpos,ai->end[1].ypos);
2831 boundobj(ai->geom, &ai->geom->lowx, &ai->geom->highx, &ai->geom->lowy, &ai->geom->highy);
2832 }
2833 db_boundcell(np, &np->lowx, &np->highx, &np->lowy, &np->highy);
2834 io_fixrtree(np->rtree);
2835 }
2836
2837 /* now restore the technology lambda values */
2838 if (lib != el_curlib)
2839 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
2840 changetechnologylambda(tech, el_curlib->lambda[tech->techindex]);
2841 }
2842
2843 #define OLDSIZE 01700
2844 #define OLDSIZESH 6
2845 #define OLDTXT4P 0 /* 4 point text */
2846 #define OLDTXT6P 1 /* 6 point text */
2847 #define OLDTXT8P 2 /* 8 point text */
2848 #define OLDTXT10P 3 /* 10 point text */
2849 #define OLDTXT12P 4 /* 12 point text */
2850 #define OLDTXT14P 5 /* 14 point text */
2851 #define OLDTXT16P 6 /* 16 point text */
2852 #define OLDTXT18P 7 /* 18 point text */
2853 #define OLDTXT20P 8 /* 20 point text */
2854 #define OLDTXTHL 9 /* half-lambda text */
2855 #define OLDTXT1L 10 /* 1-lambda text */
2856 #define OLDTXT2L 11 /* 2-lambda text */
2857 #define OLDTXT3L 12 /* 3-lambda text */
2858 #define OLDTXT4L 13 /* 4-lambda text */
2859 #define OLDTXT5L 14 /* 5-lambda text */
2860 #define OLDTXT6L 15 /* 6-lambda text */
2861
2862 #define OLDOFFSCALE 07700000000 /* old scale of text offset */
2863
2864 /*
2865 * Routine to do conversion "how" on every text descriptor in library "lib".
2866 * If "how" is 0, convert old-style text sizes to new style
2867 * If "how" is 1, shorten the text offset scale field by 1 bit
2868 */
io_converteverytextdescriptor(LIBRARY * lib,INTBIG how)2869 void io_converteverytextdescriptor(LIBRARY *lib, INTBIG how)
2870 {
2871 REGISTER NODEPROTO *np;
2872 REGISTER NODEINST *ni;
2873 REGISTER ARCINST *ai;
2874 REGISTER PORTARCINST *pi;
2875 REGISTER PORTEXPINST *pe;
2876 REGISTER PORTPROTO *pp;
2877
2878 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2879 {
2880 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
2881 {
2882 io_convertalltextdescriptors(ni->numvar, ni->firstvar, how);
2883 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2884 io_convertalltextdescriptors(pi->numvar, pi->firstvar, how);
2885 for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
2886 io_convertalltextdescriptors(pe->numvar, pe->firstvar, how);
2887 if (ni->proto->primindex == 0)
2888 io_converttextdescriptor(ni->textdescript, how);
2889 }
2890 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
2891 io_convertalltextdescriptors(ai->numvar, ai->firstvar, how);
2892 for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
2893 {
2894 io_convertalltextdescriptors(pp->numvar, pp->firstvar, how);
2895 io_converttextdescriptor(pp->textdescript, how);
2896 }
2897 io_convertalltextdescriptors(np->numvar, np->firstvar, how);
2898 }
2899 io_convertalltextdescriptors(lib->numvar, lib->firstvar, how);
2900 }
2901
2902 /*
2903 * Routine to do conversion "how" on all text descriptors on all "numvar" variables
2904 * in "firstvar".
2905 */
io_convertalltextdescriptors(INTSML numvar,VARIABLE * firstvar,INTBIG how)2906 void io_convertalltextdescriptors(INTSML numvar, VARIABLE *firstvar, INTBIG how)
2907 {
2908 REGISTER INTBIG i;
2909 REGISTER VARIABLE *var;
2910
2911 for(i=0; i<numvar; i++)
2912 {
2913 var = &firstvar[i];
2914 io_converttextdescriptor(var->textdescript, how);
2915 }
2916 }
2917
2918 /*
2919 * Routine to do conversion "how" on text descriptor "descript".
2920 */
io_converttextdescriptor(UINTBIG * descript,INTBIG how)2921 void io_converttextdescriptor(UINTBIG *descript, INTBIG how)
2922 {
2923 REGISTER INTBIG size, oldscale;
2924
2925 switch (how)
2926 {
2927 case 0: /* convert size information */
2928 size = (descript[0]&OLDSIZE) >> OLDSIZESH;
2929 switch (size)
2930 {
2931 case OLDTXT4P: size = TXTSETPOINTS(4); break;
2932 case OLDTXT6P: size = TXTSETPOINTS(6); break;
2933 case OLDTXT8P: size = TXTSETPOINTS(8); break;
2934 case OLDTXT10P: size = TXTSETPOINTS(10); break;
2935 case OLDTXT12P: size = TXTSETPOINTS(12); break;
2936 case OLDTXT14P: size = TXTSETPOINTS(14); break;
2937 case OLDTXT16P: size = TXTSETPOINTS(16); break;
2938 case OLDTXT18P: size = TXTSETPOINTS(18); break;
2939 case OLDTXT20P: size = TXTSETPOINTS(20); break;
2940 case OLDTXTHL: size = TXTSETQLAMBDA(4/2); break;
2941 case OLDTXT1L: size = TXTSETQLAMBDA(1*4); break;
2942 case OLDTXT2L: size = TXTSETQLAMBDA(2*4); break;
2943 case OLDTXT3L: size = TXTSETQLAMBDA(3*4); break;
2944 case OLDTXT4L: size = TXTSETQLAMBDA(4*4); break;
2945 case OLDTXT5L: size = TXTSETQLAMBDA(5*4); break;
2946 case OLDTXT6L: size = TXTSETQLAMBDA(6*4); break;
2947 }
2948 descript[0] &= ~OLDSIZE;
2949 descript[1] = size << VTSIZESH;
2950 break;
2951
2952 case 1: /* shorten offset scale field */
2953 oldscale = descript[1] & OLDOFFSCALE;
2954 descript[1] = (descript[1] & ~VTOFFSCALE) | (oldscale & VTOFFSCALE);
2955 break;
2956 }
2957 }
2958
io_fixupnodeinst(NODEINST * ni,INTBIG dlx,INTBIG dly,INTBIG dhx,INTBIG dhy)2959 void io_fixupnodeinst(NODEINST *ni, INTBIG dlx, INTBIG dly, INTBIG dhx, INTBIG dhy)
2960 {
2961 REGISTER PORTARCINST *pi;
2962 REGISTER ARCINST *ai;
2963
2964 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2965 {
2966 ai = pi->conarcinst;
2967 (void)(*el_curconstraint->setobject)((INTBIG)ai, VARCINST, CHANGETYPETEMPUNRIGID, 0);
2968 }
2969 modifynodeinst(ni, dlx, dly, dhx, dhy, 0, 0);
2970 }
2971
io_convertallrelativetext(INTSML numvar,VARIABLE * firstvar)2972 void io_convertallrelativetext(INTSML numvar, VARIABLE *firstvar)
2973 {
2974 REGISTER INTBIG i;
2975 REGISTER VARIABLE *var;
2976
2977 for(i=0; i<numvar; i++)
2978 {
2979 var = &firstvar[i];
2980 io_convertrelativetext(var->textdescript);
2981 }
2982 }
2983
io_convertrelativetext(UINTBIG * descript)2984 void io_convertrelativetext(UINTBIG *descript)
2985 {
2986 REGISTER INTBIG size;
2987
2988 size = (descript[0]&OLDSIZE) >> OLDSIZESH;
2989 if (size >= OLDTXT4P && size <= OLDTXT20P) return;
2990
2991 if (size <= 13)
2992 {
2993 /* TXTSMALL */
2994 descript[0] = (descript[0] & ~OLDSIZE) | (OLDTXT1L << OLDSIZESH);
2995 return;
2996 }
2997
2998 if (size == 14)
2999 {
3000 /* TXTMEDIUM */
3001 descript[0] = (descript[0] & ~OLDSIZE) | (OLDTXT2L << OLDSIZESH);
3002 return;
3003 }
3004
3005 /* TXTLARGE */
3006 descript[0] = (descript[0] & ~OLDSIZE) | (OLDTXT3L << OLDSIZESH);
3007 }
3008
3009 /*
3010 * Routine to convert old primitive names to their proper nodeprotos.
3011 */
io_convertoldprimitives(TECHNOLOGY * tech,CHAR * name)3012 NODEPROTO *io_convertoldprimitives(TECHNOLOGY *tech, CHAR *name)
3013 {
3014 if (namesame(name, x_("Cell-Center")) == 0) return(gen_cellcenterprim);
3015 if (tech == art_tech)
3016 {
3017 if (namesame(name, x_("Message")) == 0 ||
3018 namesame(name, x_("Centered-Message")) == 0 ||
3019 namesame(name, x_("Left-Message")) == 0 ||
3020 namesame(name, x_("Right-Message")) == 0) return(gen_invispinprim);
3021 if (namesame(name, x_("Opened-FarDotted-Polygon")) == 0)
3022 return(art_openedthickerpolygonprim);
3023 }
3024 if (tech == mocmos_tech)
3025 {
3026 if (namesame(name, x_("Metal-1-Substrate-Con")) == 0)
3027 return(mocmos_metal1nwellprim);
3028 if (namesame(name, x_("Metal-1-Well-Con")) == 0)
3029 return(mocmos_metal1pwellprim);
3030 }
3031 return(NONODEPROTO);
3032 }
3033
3034 /*
3035 * Routine to convert old libraries that have no cellgroup pointers. Finds
3036 * matching names and presumes that they are in the same cellgroup.
3037 */
io_buildcellgrouppointersfromnames(LIBRARY * lib)3038 void io_buildcellgrouppointersfromnames(LIBRARY *lib)
3039 {
3040 REGISTER NODEPROTO *np, *onp, *prevmatch;
3041
3042 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3043 np->nextcellgrp = np;
3044 for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3045 {
3046 /* ignore old versions */
3047 if (np->newestversion != np) continue;
3048
3049 /* skip if already in a cellgroup */
3050 if (np->nextcellgrp != np) continue;
3051
3052 /* find others in this cell group */
3053 prevmatch = np;
3054 for(onp = np->nextnodeproto; onp != NONODEPROTO; onp = onp->nextnodeproto)
3055 {
3056 /* ignore old versions */
3057 if (onp->newestversion != onp) continue;
3058
3059 /* ignore if the name doesn't match */
3060 if (namesame(np->protoname, onp->protoname) != 0) continue;
3061
3062 /* add this to the cellgroup */
3063 prevmatch->nextcellgrp = onp;
3064 prevmatch = onp;
3065 }
3066
3067 /* make this cellgroup's list circular */
3068 if (prevmatch != np)
3069 prevmatch->nextcellgrp = np;
3070 }
3071 }
3072
3073 /*
3074 * Routine to find the version of Electric that generated library "lib" and
3075 * parse it into three fields: the major version number, minor version, and
3076 * a detail version number.
3077 */
io_getversion(LIBRARY * lib,INTBIG * major,INTBIG * minor,INTBIG * detail)3078 void io_getversion(LIBRARY *lib, INTBIG *major, INTBIG *minor, INTBIG *detail)
3079 {
3080 REGISTER VARIABLE *var;
3081 INTBIG emajor, eminor, edetail;
3082 CHAR *libversion;
3083
3084 var = getval((INTBIG)lib, VLIBRARY, VSTRING, x_("LIB_former_version"));
3085 if (var == NOVARIABLE)
3086 {
3087 *major = *minor = *detail = 0;
3088 return;
3089 }
3090 libversion = (CHAR *)var->addr;
3091 parseelectricversion(libversion, major, minor, detail);
3092
3093 /* see if this library is newer than the current version of Electric */
3094 parseelectricversion(el_version, &emajor, &eminor, &edetail);
3095 if (*major > emajor ||
3096 (*major == emajor && *minor > eminor) ||
3097 (*major == emajor && *minor == eminor && *detail > edetail))
3098 {
3099 ttyputerr(_("Warning: library %s comes from a NEWER version of Electric (%s)"),
3100 lib->libname, libversion);
3101 }
3102 }
3103
3104 /* Technology: Lambda Adjustment */
3105 static DIALOGITEM io_techadjlamdialogitems[] =
3106 {
3107 /* 1 */ {0, {232,220,256,300}, BUTTON, N_("Done")},
3108 /* 2 */ {0, {204,264,220,512}, BUTTON, N_("Use New Size for all Technologies")},
3109 /* 3 */ {0, {204,8,220,256}, BUTTON, N_("Use Current Size for all Technologies")},
3110 /* 4 */ {0, {28,300,128,512}, SCROLL, x_("")},
3111 /* 5 */ {0, {148,8,164,164}, MESSAGE, N_("Current lambda size:")},
3112 /* 6 */ {0, {148,264,164,416}, MESSAGE, N_("New lambda size:")},
3113 /* 7 */ {0, {148,164,164,256}, MESSAGE, x_("")},
3114 /* 8 */ {0, {148,416,164,512}, MESSAGE, x_("")},
3115 /* 9 */ {0, {176,264,192,512}, BUTTON, N_("<< Use New Size in Current Library")},
3116 /* 10 */ {0, {176,8,192,256}, BUTTON, N_("Use Current Size in New Library >>")},
3117 /* 11 */ {0, {80,16,96,292}, MESSAGE, N_("and choose from the actions below.")},
3118 /* 12 */ {0, {8,8,24,508}, MESSAGE, N_("This new library uses different lambda values than existing libraries.")},
3119 /* 13 */ {0, {28,8,44,292}, MESSAGE, N_("You should unify the lambda values.")},
3120 /* 14 */ {0, {60,8,76,292}, MESSAGE, N_("Click on each technology in this list")},
3121 /* 15 */ {0, {136,8,137,512}, DIVIDELINE, x_("")},
3122 /* 16 */ {0, {112,8,128,284}, MESSAGE, N_("Use 'Check and Repair Libraries' when done.")}
3123 };
3124 static DIALOG io_techadjlamdialog = {{75,75,340,596}, N_("Lambda Value Adjustment"), 0, 16, io_techadjlamdialogitems, 0, 0};
3125
3126 /* special items for the "lambda adjustment" dialog: */
3127 #define DTLA_USENEWALWAYS 2 /* Use new unit always (button) */
3128 #define DTLA_USECURALWAYS 3 /* Use current unit always (button) */
3129 #define DTLA_TECHLIST 4 /* List of technologies (scroll) */
3130 #define DTLA_CURLAMBDA 7 /* Current lambda value (stat text) */
3131 #define DTLA_NEWLAMBDA 8 /* New lambda value (stat text) */
3132 #define DTLA_USENEW 9 /* Use new unit (button) */
3133 #define DTLA_USECUR 10 /* Use current unit (button) */
3134
3135 /*
3136 * Routine to examine new library "lib" and make sure that the lambda values in it are
3137 * the same as existing libraries/technologies. Automatically adjusts values if possible,
3138 * and prompts the user to help out if necessary.
3139 */
io_unifylambdavalues(LIBRARY * lib)3140 void io_unifylambdavalues(LIBRARY *lib)
3141 {
3142 REGISTER TECHNOLOGY *tech, *otech, **techarray;
3143 REGISTER LIBRARY *olib;
3144 REGISTER NODEPROTO *np, **libcells;
3145 REGISTER NODEINST *ni;
3146 REGISTER ARCINST *ai;
3147 REGISTER INTBIG itemHit, i, count, recompute, newunit, curunit, *newlamarray,
3148 oldbits;
3149 REGISTER CHAR *pt;
3150 float lambdainmicrons;
3151 CHAR line[50];
3152 REGISTER void *dia;
3153
3154 /* see if this library has incompatible lambda values */
3155 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3156 {
3157 if (tech == art_tech) continue;
3158 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3159 {
3160 if (lib->lambda[tech->techindex] != olib->lambda[tech->techindex])
3161 break;
3162 }
3163 if (olib != NOLIBRARY) break;
3164 }
3165 if (tech == NOTECHNOLOGY) return;
3166
3167 /* this library has different values: check usage in this and other libraries */
3168 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3169 {
3170 olib->temp1 = (INTBIG)emalloc(el_maxtech * (sizeof (NODEPROTO *)), el_tempcluster);
3171 if (olib->temp1 == 0) return;
3172 for(i=0; i<el_maxtech; i++) ((NODEPROTO **)olib->temp1)[i] = NONODEPROTO;
3173 }
3174 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3175 {
3176 libcells = (NODEPROTO **)olib->temp1;
3177 for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3178 {
3179 for(ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3180 {
3181 if (ni->proto->primindex == 0) continue;
3182 tech = ni->proto->tech;
3183 libcells[tech->techindex] = np;
3184 }
3185 for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
3186 {
3187 tech = ai->proto->tech;
3188 libcells[tech->techindex] = np;
3189 }
3190 }
3191 }
3192
3193 /* see if there are inconsistencies that cannot be automatically resolved */
3194 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3195 {
3196 if (tech == art_tech) continue;
3197 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3198 {
3199 if (((NODEPROTO **)olib->temp1)[tech->techindex] == NONODEPROTO) continue;
3200 if (((NODEPROTO **)lib->temp1)[tech->techindex] == NONODEPROTO) continue;
3201 if (lib->lambda[tech->techindex] != olib->lambda[tech->techindex])
3202 break;
3203 }
3204 if (olib != NOLIBRARY) break;
3205 }
3206 if (tech != NOTECHNOLOGY)
3207 {
3208 /* get the user to resolve the inconsistencies */
3209 dia = DiaInitDialog(&io_techadjlamdialog);
3210 if (dia == 0) return;
3211 DiaInitTextDialog(dia, DTLA_TECHLIST, DiaNullDlogList, DiaNullDlogItem,
3212 DiaNullDlogDone, -1, SCSELMOUSE|SCREPORT);
3213 DiaUnDimItem(dia, DTLA_USECURALWAYS);
3214 DiaUnDimItem(dia, DTLA_USENEWALWAYS);
3215 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3216 {
3217 if (tech == art_tech) continue;
3218 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3219 {
3220 if (((NODEPROTO **)olib->temp1)[tech->techindex] == NONODEPROTO) continue;
3221 if (((NODEPROTO **)lib->temp1)[tech->techindex] == NONODEPROTO) continue;
3222 if (lib->lambda[tech->techindex] != olib->lambda[tech->techindex])
3223 break;
3224 }
3225 if (olib == NOLIBRARY) continue;
3226 DiaStuffLine(dia, DTLA_TECHLIST, tech->techname);
3227 }
3228 DiaSelectLine(dia, DTLA_TECHLIST, 0);
3229 recompute = 1;
3230 tech = NOTECHNOLOGY;
3231 for(;;)
3232 {
3233 if (recompute != 0)
3234 {
3235 recompute = 0;
3236
3237 /* figure out which technology is selected */
3238 i = DiaGetCurLine(dia, DTLA_TECHLIST);
3239 pt = DiaGetScrollLine(dia, DTLA_TECHLIST, i);
3240 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3241 if (namesame(pt, tech->techname) == 0) break;
3242 if (tech == NOTECHNOLOGY) continue;
3243
3244 /* figure out which units are in force */
3245 curunit = newunit = lib->lambda[tech->techindex];
3246 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3247 {
3248 if ((olib->userbits&HIDDENLIBRARY) != 0) continue;
3249 if (((NODEPROTO **)olib->temp1)[tech->techindex] == NONODEPROTO) continue;
3250 if (((NODEPROTO **)olib->temp1)[tech->techindex] == 0) continue;
3251 if (olib->lambda[tech->techindex] != lib->lambda[tech->techindex]) break;
3252 }
3253 if (olib != NOLIBRARY) curunit = olib->lambda[tech->techindex];
3254
3255 /* see if it has already been overridden */
3256 if (((INTBIG *)lib->temp1)[tech->techindex] == 0) newunit = curunit;
3257
3258 /* set dialog values and offer choices */
3259 lambdainmicrons = scaletodispunit(curunit, DISPUNITMIC);
3260 esnprintf(line, 50, x_("%gu"), lambdainmicrons);
3261 DiaSetText(dia, DTLA_CURLAMBDA, line);
3262 lambdainmicrons = scaletodispunit(newunit, DISPUNITMIC);
3263 esnprintf(line, 50, x_("%gu"), lambdainmicrons);
3264 DiaSetText(dia, DTLA_NEWLAMBDA, line);
3265 if (newunit == curunit)
3266 {
3267 DiaDimItem(dia, DTLA_USENEW);
3268 DiaDimItem(dia, DTLA_USECUR);
3269 } else
3270 {
3271 DiaUnDimItem(dia, DTLA_USENEW);
3272 DiaUnDimItem(dia, DTLA_USECUR);
3273 }
3274 }
3275 itemHit = DiaNextHit(dia);
3276 if (itemHit == OK) break;
3277 if (itemHit == DTLA_TECHLIST) recompute = 1;
3278 if (itemHit == DTLA_USENEW)
3279 {
3280 /* use new unit */
3281 if (tech != NOTECHNOLOGY)
3282 {
3283 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3284 {
3285 if ((olib->userbits&HIDDENLIBRARY) != 0) continue;
3286 if (((NODEPROTO **)olib->temp1)[tech->techindex] == NONODEPROTO) continue;
3287 ((NODEPROTO **)olib->temp1)[tech->techindex] = 0;
3288 }
3289 }
3290 recompute = 1;
3291 continue;
3292 }
3293 if (itemHit == DTLA_USENEWALWAYS)
3294 {
3295 /* use new unit always */
3296 for(otech = el_technologies; otech != NOTECHNOLOGY; otech = otech->nexttechnology)
3297 {
3298 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3299 {
3300 if ((olib->userbits&HIDDENLIBRARY) != 0) continue;
3301 if (((NODEPROTO **)olib->temp1)[otech->techindex] == NONODEPROTO) continue;
3302 ((NODEPROTO **)olib->temp1)[otech->techindex] = 0;
3303 }
3304 }
3305 recompute = 1;
3306 DiaDimItem(dia, DTLA_USECURALWAYS);
3307 DiaDimItem(dia, DTLA_USENEWALWAYS);
3308 continue;
3309 }
3310 if (itemHit == DTLA_USECURALWAYS)
3311 {
3312 /* use current unit always */
3313 for(otech = el_technologies; otech != NOTECHNOLOGY; otech = otech->nexttechnology)
3314 ((NODEPROTO **)lib->temp1)[otech->techindex] = 0;
3315 recompute = 1;
3316 DiaDimItem(dia, DTLA_USECURALWAYS);
3317 DiaDimItem(dia, DTLA_USENEWALWAYS);
3318 continue;
3319 }
3320 if (itemHit == DTLA_USECUR)
3321 {
3322 /* use current unit */
3323 if (tech != NOTECHNOLOGY) ((NODEPROTO **)lib->temp1)[tech->techindex] = 0;
3324 recompute = 1;
3325 continue;
3326 }
3327 }
3328 DiaDoneDialog(dia);
3329 }
3330
3331 /* do automatic conversions */
3332 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3333 {
3334 if (tech == art_tech) continue;
3335 if (((NODEPROTO **)lib->temp1)[tech->techindex] == NONODEPROTO)
3336 ((NODEPROTO **)lib->temp1)[tech->techindex] = 0;
3337 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3338 {
3339 if (((NODEPROTO **)olib->temp1)[tech->techindex] == NONODEPROTO)
3340 ((NODEPROTO **)olib->temp1)[tech->techindex] = 0;
3341 }
3342 }
3343
3344 /* adjust lambda values in old libraries to match this one */
3345 techarray = (TECHNOLOGY **)emalloc(el_maxtech * (sizeof (TECHNOLOGY *)), el_tempcluster);
3346 if (techarray == 0) return;
3347 newlamarray = (INTBIG *)emalloc(el_maxtech * SIZEOFINTBIG, el_tempcluster);
3348 if (newlamarray == 0) return;
3349 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3350 {
3351 if (olib == lib) continue;
3352
3353 /* see how many technologies are affected */
3354 count = 0;
3355 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3356 {
3357 if (((NODEPROTO **)olib->temp1)[tech->techindex] != 0) continue;
3358 if (lib->lambda[tech->techindex] == olib->lambda[tech->techindex]) continue;
3359 techarray[count] = tech;
3360 newlamarray[count] = lib->lambda[tech->techindex];
3361 count++;
3362 }
3363 if (count == 0) continue;
3364
3365 /* adjust this library */
3366 oldbits = olib->userbits;
3367 changelambda(count, techarray, newlamarray, olib, 1);
3368 olib->userbits = (olib->userbits & ~LIBCHANGEDMAJOR) |
3369 (oldbits & LIBCHANGEDMAJOR);
3370 }
3371
3372 /* change lambda values in this library to match old ones */
3373 count = 0;
3374 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3375 {
3376 if (((NODEPROTO **)lib->temp1)[tech->techindex] != 0) continue;
3377 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3378 {
3379 if ((olib->userbits&HIDDENLIBRARY) != 0) continue;
3380 if (olib->lambda[tech->techindex] == lib->lambda[tech->techindex]) continue;
3381 if (((NODEPROTO **)olib->temp1)[tech->techindex] != 0) break;
3382 }
3383 if (olib == NOLIBRARY) continue;
3384 techarray[count] = tech;
3385 newlamarray[count] = olib->lambda[tech->techindex];
3386 count++;
3387 }
3388 if (count != 0)
3389 {
3390 /* adjust new library */
3391 changelambda(count, techarray, newlamarray, lib, 1);
3392 }
3393
3394 /* free memory used here */
3395 efree((CHAR *)techarray);
3396 efree((CHAR *)newlamarray);
3397 for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
3398 efree((CHAR *)olib->temp1);
3399 }
3400
3401 /****************************** LIBRARY OPTIONS DIALOG ******************************/
3402
3403 /* Library: Options */
3404 static DIALOGITEM io_liboptdialogitems[] =
3405 {
3406 /* 1 */ {0, {124,148,148,228}, BUTTON, N_("OK")},
3407 /* 2 */ {0, {124,16,148,96}, BUTTON, N_("Cancel")},
3408 /* 3 */ {0, {8,8,24,236}, RADIO, N_("No backup of library files")},
3409 /* 4 */ {0, {32,8,48,236}, RADIO, N_("Backup of last library file")},
3410 /* 5 */ {0, {56,8,72,236}, RADIO, N_("Backup history of library files")},
3411 /* 6 */ {0, {92,8,108,236}, CHECK, N_("Check database after write")}
3412 };
3413 static DIALOG io_liboptdialog = {{75,75,232,321}, N_("Library Options"), 0, 6, io_liboptdialogitems, 0, 0};
3414
3415 /* special items for the "library options" dialog: */
3416 #define DLBO_NOBACKUP 3 /* no backup (radio) */
3417 #define DLBO_ONEBACKUP 4 /* backup one level (radio) */
3418 #define DLBO_FULLBACKUP 5 /* backup history (radio) */
3419 #define DLBO_CHECKAFTERWRITE 6 /* check after write (check) */
3420
io_libraryoptiondlog(void)3421 void io_libraryoptiondlog(void)
3422 {
3423 INTBIG itemHit, i, *origstate, curstate[NUMIOSTATEBITWORDS];
3424 REGISTER void *dia;
3425
3426 /* display the library paths dialog box */
3427 dia = DiaInitDialog(&io_liboptdialog);
3428 if (dia == 0) return;
3429
3430 /* get current state of I/O tool */
3431 origstate = io_getstatebits();
3432 for(i=0; i<NUMIOSTATEBITWORDS; i++) curstate[i] = origstate[i];
3433 switch (curstate[0]&BINOUTBACKUP)
3434 {
3435 case BINOUTNOBACK: DiaSetControl(dia, DLBO_NOBACKUP, 1); break;
3436 case BINOUTONEBACK: DiaSetControl(dia, DLBO_ONEBACKUP, 1); break;
3437 case BINOUTFULLBACK: DiaSetControl(dia, DLBO_FULLBACKUP, 1); break;
3438 }
3439 if ((curstate[0]&CHECKATWRITE) != 0) DiaSetControl(dia, DLBO_CHECKAFTERWRITE, 1);
3440
3441 /* loop until done */
3442 for(;;)
3443 {
3444 itemHit = DiaNextHit(dia);
3445 if (itemHit == OK || itemHit == CANCEL) break;
3446 if (itemHit == DLBO_NOBACKUP || itemHit == DLBO_ONEBACKUP ||
3447 itemHit == DLBO_FULLBACKUP)
3448 {
3449 DiaSetControl(dia, DLBO_NOBACKUP, 0);
3450 DiaSetControl(dia, DLBO_ONEBACKUP, 0);
3451 DiaSetControl(dia, DLBO_FULLBACKUP, 0);
3452 DiaSetControl(dia, itemHit, 1);
3453 continue;
3454 }
3455 if (itemHit == DLBO_CHECKAFTERWRITE)
3456 {
3457 DiaSetControl(dia, itemHit, 1 - DiaGetControl(dia, itemHit));
3458 continue;
3459 }
3460 }
3461
3462 if (itemHit != CANCEL)
3463 {
3464 curstate[0] &= ~(BINOUTBACKUP|CHECKATWRITE);
3465 if (DiaGetControl(dia, DLBO_ONEBACKUP) != 0) curstate[0] |= BINOUTONEBACK; else
3466 if (DiaGetControl(dia, DLBO_FULLBACKUP) != 0) curstate[0] |= BINOUTFULLBACK;
3467 if (DiaGetControl(dia, DLBO_CHECKAFTERWRITE) != 0) curstate[0] |= CHECKATWRITE;
3468 for(i=0; i<NUMIOSTATEBITWORDS; i++)
3469 if (curstate[i] != origstate[i]) break;
3470 if (i < NUMIOSTATEBITWORDS)
3471 io_setstatebits(curstate);
3472 }
3473 DiaDoneDialog(dia);
3474 }
3475
3476 /* CDL Options */
3477 static DIALOGITEM io_cdloptdialogitems[] =
3478 {
3479 /* 1 */ {0, {100,236,124,316}, BUTTON, N_("OK")},
3480 /* 2 */ {0, {100,64,124,144}, BUTTON, N_("Cancel")},
3481 /* 3 */ {0, {8,8,24,184}, MESSAGE, N_("Cadence Library Name:")},
3482 /* 4 */ {0, {8,187,24,363}, EDITTEXT, x_("")},
3483 /* 5 */ {0, {32,8,48,184}, MESSAGE, N_("Cadence Library Path:")},
3484 /* 6 */ {0, {32,187,64,363}, EDITTEXT, x_("")},
3485 /* 7 */ {0, {72,8,88,176}, CHECK, N_("Convert brackets")}
3486 };
3487 static DIALOG io_cdloptdialog = {{75,75,208,447}, N_("CDL Options"), 0, 7, io_cdloptdialogitems, 0, 0};
3488
3489 /* special items for the "CDL Options" dialog: */
3490 #define DCDL_LIBNAME 4 /* Cadence Library Name (edit text) */
3491 #define DCDL_LIBPATH 6 /* Cadence Library Path (edit text) */
3492 #define DCDL_CONVBRACKET 7 /* Convert brackets (check) */
3493
3494 /*
3495 * Routine to run the CDL Options dialog.
3496 */
io_cdloptionsdialog(void)3497 void io_cdloptionsdialog(void)
3498 {
3499 INTBIG i, itemHit, *curstate, newstate[NUMIOSTATEBITWORDS];
3500 REGISTER VARIABLE *var;
3501 REGISTER CHAR *inilibname, *inilibpath;
3502 BOOLEAN libnamechanged, libpathchanged;
3503 REGISTER void *dia;
3504
3505 dia = DiaInitDialog(&io_cdloptdialog);
3506 if (dia == 0) return;
3507 var = getval((INTBIG)io_tool, VTOOL, VSTRING, x_("IO_cdl_library_name"));
3508 if (var == NOVARIABLE) inilibname = x_(""); else
3509 inilibname = (CHAR *)var->addr;
3510 DiaSetText(dia, DCDL_LIBNAME, inilibname);
3511 var = getval((INTBIG)io_tool, VTOOL, VSTRING, x_("IO_cdl_library_path"));
3512 if (var == NOVARIABLE) inilibpath = x_(""); else
3513 inilibpath = (CHAR *)var->addr;
3514 DiaSetText(dia, DCDL_LIBPATH, inilibpath);
3515 curstate = io_getstatebits();
3516 if ((curstate[1]&CDLNOBRACKETS) != 0) DiaSetControl(dia, DCDL_CONVBRACKET, 1);
3517
3518 libnamechanged = libpathchanged = FALSE;
3519 for(;;)
3520 {
3521 itemHit = DiaNextHit(dia);
3522 if (itemHit == OK || itemHit == CANCEL) break;
3523 if (itemHit == DCDL_CONVBRACKET)
3524 {
3525 DiaSetControl(dia, itemHit, 1 - DiaGetControl(dia, itemHit));
3526 continue;
3527 }
3528 if (itemHit == DCDL_LIBNAME)
3529 {
3530 if (estrcmp(inilibname, DiaGetText(dia, DCDL_LIBNAME)) != 0)
3531 libnamechanged = TRUE;
3532 continue;
3533 }
3534 if (itemHit == DCDL_LIBPATH)
3535 {
3536 if (estrcmp(inilibpath, DiaGetText(dia, DCDL_LIBPATH)) != 0)
3537 libpathchanged = TRUE;
3538 continue;
3539 }
3540 }
3541 if (itemHit == OK)
3542 {
3543 if (libnamechanged != 0)
3544 {
3545 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_cdl_library_name"),
3546 (INTBIG)DiaGetText(dia, DCDL_LIBNAME), VSTRING);
3547 }
3548 if (libpathchanged != 0)
3549 {
3550 (void)setval((INTBIG)io_tool, VTOOL, x_("IO_cdl_library_path"),
3551 (INTBIG)DiaGetText(dia, DCDL_LIBPATH), VSTRING);
3552 }
3553 for(i=0; i<NUMIOSTATEBITWORDS; i++) newstate[i] = curstate[i];
3554 if (DiaGetControl(dia, DCDL_CONVBRACKET) != 0) newstate[1] |= CDLNOBRACKETS; else
3555 newstate[1] &= ~CDLNOBRACKETS;
3556 for(i=0; i<NUMIOSTATEBITWORDS; i++) if (curstate[i] != newstate[i]) break;
3557 if (i < NUMIOSTATEBITWORDS) io_setstatebits(newstate);
3558 }
3559 DiaDoneDialog(dia);
3560 }
3561
3562 /* Sue Options */
3563 static DIALOGITEM io_sueoptdialogitems[] =
3564 {
3565 /* 1 */ {0, {36,120,60,192}, BUTTON, N_("OK")},
3566 /* 2 */ {0, {36,16,60,88}, BUTTON, N_("Cancel")},
3567 /* 3 */ {0, {8,8,24,200}, CHECK, N_("Make 4-port transistors")}
3568 };
3569 static DIALOG io_sueoptdialog = {{50,75,119,285}, N_("SUE Options"), 0, 3, io_sueoptdialogitems, 0, 0};
3570
3571 /* special items for the "Sue Options" dialog: */
3572 #define DSUE_USE4PORTS 3 /* Use 4-port transistors (check) */
3573
3574 /*
3575 * Routine to run the Sue Options dialog.
3576 */
io_sueoptionsdialog(void)3577 void io_sueoptionsdialog(void)
3578 {
3579 INTBIG i, itemHit, *curstate, newstate[NUMIOSTATEBITWORDS];
3580 REGISTER void *dia;
3581
3582 dia = DiaInitDialog(&io_sueoptdialog);
3583 if (dia == 0) return;
3584 curstate = io_getstatebits();
3585 if ((curstate[1]&SUEUSE4PORTTRANS) != 0) DiaSetControl(dia, DSUE_USE4PORTS, 1);
3586
3587 for(;;)
3588 {
3589 itemHit = DiaNextHit(dia);
3590 if (itemHit == OK || itemHit == CANCEL) break;
3591 if (itemHit == DSUE_USE4PORTS)
3592 {
3593 DiaSetControl(dia, itemHit, 1 - DiaGetControl(dia, itemHit));
3594 continue;
3595 }
3596 }
3597 if (itemHit == OK)
3598 {
3599 for(i=0; i<NUMIOSTATEBITWORDS; i++) newstate[i] = curstate[i];
3600 if (DiaGetControl(dia, DSUE_USE4PORTS) != 0) newstate[1] |= SUEUSE4PORTTRANS; else
3601 newstate[1] &= ~SUEUSE4PORTTRANS;
3602 for(i=0; i<NUMIOSTATEBITWORDS; i++) if (curstate[i] != newstate[i]) break;
3603 if (i < NUMIOSTATEBITWORDS) io_setstatebits(newstate);
3604 }
3605 DiaDoneDialog(dia);
3606 }
3607
3608 #define VARTYPELAYTOLAY 0 /* this variable is a layer-to-layer list */
3609 #define VARTYPELAYER 1 /* this variable is a layer list */
3610 #define VARTYPELAYERNONDRC 2 /* this variable is a layer list, not related to DRC */
3611 #define VARTYPENODE 3 /* this variable is a node list */
3612 #define VARTYPENODE2 4 /* this variable has 2 entries per node */
3613
3614 static struct
3615 {
3616 CHAR *variable;
3617 CHAR *meaning;
3618 INTBIG variabletype;
3619 INTBIG key;
3620 INTBIG defaultint;
3621 CHAR *defaultstring;
3622 float defaultfloat;
3623 } io_techlayervariables[] =
3624 {
3625 {x_("IO_cif_layer_names"), N_("CIF Layer Names"), VARTYPELAYERNONDRC,0, 0, x_(""), 0.0},
3626 {x_("IO_dxf_layer_names"), N_("DXF Layer Names"), VARTYPELAYERNONDRC,0, 0, x_(""), 0.0},
3627 {x_("IO_gds_layer_numbers"), N_("GDS Layer Numbers"), VARTYPELAYERNONDRC,0, -1, x_(""), 0.0},
3628 {x_("IO_skill_layer_names"), N_("SKILL Layer Names"), VARTYPELAYERNONDRC,0, 0, x_(""), 0.0},
3629 {x_("SIM_spice_resistance"), N_("SPICE Layer Resistances"), VARTYPELAYERNONDRC,0, 0, x_(""), 0.0},
3630 {x_("SIM_spice_capacitance"), N_("SPICE Layer Capacitances"), VARTYPELAYERNONDRC,0, 0, x_(""), 0.0},
3631 {x_("DRC_min_connected_distances"), N_("Normal Connected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3632 {x_("DRC_min_connected_distances_rule"), N_("Normal Connected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3633 {x_("DRC_min_unconnected_distances"), N_("Normal Unconnected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3634 {x_("DRC_min_unconnected_distances_rule"), N_("Normal Unconnected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3635 {x_("DRC_min_connected_distances_wide"), N_("Wide Connected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3636 {x_("DRC_min_connected_distances_wide_rule"), N_("Wide Connected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3637 {x_("DRC_min_unconnected_distances_wide"), N_("Wide Unconnected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3638 {x_("DRC_min_unconnected_distances_wide_rule"), N_("Wide Unconnected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3639 {x_("DRC_min_connected_distances_multi"), N_("Multicut Connected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3640 {x_("DRC_min_connected_distances_multi_rule"), N_("Multicut Connected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3641 {x_("DRC_min_unconnected_distances_wide"), N_("Wide Unconnected Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3642 {x_("DRC_min_unconnected_distances_wide_rule"), N_("Wide Unconnected Design Rule"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3643 {x_("DRC_min_unconnected_distances_multi"), N_("Multicut Unconnected Design Rule spacings"),VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3644 {x_("DRC_min_edge_distances"), N_("Edge Design Rule spacings"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3645 {x_("DRC_min_edge_distances_rule"), N_("Edge Design Rules"), VARTYPELAYTOLAY, 0, -WHOLE, x_(""), 0.0},
3646 {x_("DRC_min_width"), N_("Minimum Layer Widths"), VARTYPELAYER, 0, -WHOLE, x_(""), 0.0},
3647 {x_("DRC_min_width_rule"), N_("Minimum Layer Width Rules"), VARTYPELAYER, 0, 0, x_(""), 0.0},
3648 {x_("DRC_min_node_size"), N_("Minimum Node Sizes"), VARTYPENODE2, 0, -WHOLE, x_(""), 0.0},
3649 {x_("DRC_min_node_size_rule"), N_("Minimum Node Size Rules"), VARTYPENODE, 0, 0, x_(""), 0.0},
3650 {0, 0, FALSE, 0, 0, x_(""), 0.0}
3651 };
3652
3653 /*
3654 * this table rearranges the MOSIS CMOS Submicron layer tables from
3655 * their old 4-layer metal (34 layers) to 6-layer metal (40 layers)
3656 */
3657 static INTBIG tech_mocmossubarrange[] =
3658 {
3659 0, 1, 2, 3, 6, 7, 8, 9, 10, 11,
3660 12, 13, 14, 15, 16, 17, 18, 21, 22, 23,
3661 24, 25, 26, 27, 28, 31, 32, 33, 34, 35,
3662 36, 37, 38, 39
3663 };
3664
3665 static struct
3666 {
3667 CHAR *techname;
3668 INTBIG oldlayercount, newlayercount;
3669 INTBIG *arrangement;
3670 } io_techlayerfixes[] =
3671 {
3672 {x_("mocmossub"), 34, 40, tech_mocmossubarrange},
3673 {x_("mocmos"), 34, 40, tech_mocmossubarrange},
3674 {0, 0, 0, 0}
3675 };
3676
io_fixtechlayers(LIBRARY * lib)3677 void io_fixtechlayers(LIBRARY *lib)
3678 {
3679 REGISTER INTBIG i, j, k, l, l1, l2, oldpos, newpos, newl1, newl2, *newints;
3680 REGISTER float *newfloats;
3681 REGISTER BOOLEAN factorywarned;
3682 REGISTER CHAR **newstrings;
3683 REGISTER TECHNOLOGY *tech;
3684 REGISTER VARIABLE *var;
3685
3686 factorywarned = FALSE;
3687 for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
3688 {
3689 for(i=0; io_techlayervariables[i].variable != 0; i++)
3690 {
3691 if (io_techlayervariables[i].key == 0)
3692 io_techlayervariables[i].key = makekey(io_techlayervariables[i].variable);
3693 var = getvalkey((INTBIG)tech, VTECHNOLOGY, -1, io_techlayervariables[i].key);
3694 if (var == NOVARIABLE) continue;
3695 switch (io_techlayervariables[i].variabletype)
3696 {
3697 case VARTYPELAYTOLAY:
3698 /* this variable should have one per layer-to-layer combination in the technology */
3699 l = tech->layercount;
3700 if (getlength(var) == (l * l + l) / 2) continue;
3701 break;
3702 case VARTYPELAYER:
3703 case VARTYPELAYERNONDRC:
3704 /* this variable should have one per layer in the technology */
3705 if (getlength(var) == tech->layercount) continue;
3706 break;
3707 case VARTYPENODE:
3708 /* this variable should have one per node in the technology */
3709 if (getlength(var) == tech->nodeprotocount) continue;
3710 break;
3711 case VARTYPENODE2:
3712 /* this variable should have two per node in the technology */
3713 if (getlength(var) == tech->nodeprotocount*2) continue;
3714 break;
3715 }
3716
3717 /* layers are inconsistent: see if there are rules to fix it */
3718 for(j=0; io_techlayerfixes[j].techname != 0; j++)
3719 {
3720 if (namesame(tech->techname, io_techlayerfixes[j].techname) != 0) continue;
3721 switch (io_techlayervariables[i].variabletype)
3722 {
3723 case VARTYPELAYTOLAY:
3724 l = io_techlayerfixes[j].oldlayercount;
3725 if ((l*l+l)/2 != getlength(var)) continue;
3726 break;
3727 case VARTYPELAYER:
3728 case VARTYPELAYERNONDRC:
3729 if (io_techlayerfixes[j].oldlayercount != getlength(var)) continue;
3730 break;
3731 default:
3732 continue;
3733 }
3734 if (io_techlayerfixes[j].newlayercount != tech->layercount) continue;
3735 break;
3736 }
3737 if (io_techlayerfixes[j].techname != 0)
3738 {
3739 if (io_techlayervariables[i].variabletype == VARTYPELAYTOLAY)
3740 {
3741 k = tech->layercount;
3742 l = (k * k + k)/2;
3743 newints = (INTBIG *)emalloc(l * SIZEOFINTBIG, tech->cluster);
3744 for(k=0; k<l; k++)
3745 newints[k] = io_techlayervariables[i].defaultint;
3746 for(l1=0; l1<io_techlayerfixes[j].oldlayercount; l1++)
3747 {
3748 for(l2=l1; l2<io_techlayerfixes[j].oldlayercount; l2++)
3749 {
3750 oldpos = (l1+1) * (l1/2) + (l1&1) * ((l1+1)/2);
3751 oldpos = l2 + io_techlayerfixes[j].oldlayercount * l1 - oldpos;
3752 newl1 = io_techlayerfixes[j].arrangement[l1];
3753 newl2 = io_techlayerfixes[j].arrangement[l2];
3754 newpos = (newl1+1) * (newl1/2) + (newl1&1) * ((newl1+1)/2);
3755 newpos = newl2 + tech->layercount * newl1 - newpos;
3756 newints[newpos] = ((INTBIG *)var->addr)[oldpos];
3757 }
3758 }
3759 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, io_techlayervariables[i].key,
3760 (INTBIG)newints, (var->type&VTYPE)|VISARRAY|(l<<VLENGTHSH));
3761 efree((CHAR *)newints);
3762 } else
3763 {
3764 /* able to fix the ordering */
3765 if ((var->type&VTYPE) == VSTRING)
3766 {
3767 newstrings = (CHAR **)emalloc(tech->layercount * (sizeof (CHAR *)),
3768 tech->cluster);
3769 for(k=0; k<tech->layercount; k++)
3770 newstrings[k] = io_techlayervariables[i].defaultstring;
3771 for(k=0; k<getlength(var); k++)
3772 newstrings[io_techlayerfixes[j].arrangement[k]] =
3773 ((CHAR **)var->addr)[k];
3774 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, io_techlayervariables[i].key,
3775 (INTBIG)newstrings, (var->type&VTYPE)|VISARRAY|(tech->layercount<<VLENGTHSH));
3776 efree((CHAR *)newstrings);
3777 } else if ((var->type&VTYPE) == VFLOAT)
3778 {
3779 newfloats = (float *)emalloc(tech->layercount * (sizeof (float)),
3780 tech->cluster);
3781 for(k=0; k<tech->layercount; k++)
3782 newfloats[k] = io_techlayervariables[i].defaultfloat;
3783 for(k=0; k<getlength(var); k++)
3784 newfloats[io_techlayerfixes[j].arrangement[k]] =
3785 ((float *)var->addr)[k];
3786 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, io_techlayervariables[i].key,
3787 (INTBIG)newfloats, (var->type&VTYPE)|VISARRAY|(tech->layercount<<VLENGTHSH));
3788 efree((CHAR *)newfloats);
3789 } else
3790 {
3791 newints = (INTBIG *)emalloc(tech->layercount * SIZEOFINTBIG,
3792 tech->cluster);
3793 for(k=0; k<tech->layercount; k++)
3794 newints[k] = io_techlayervariables[i].defaultint;
3795 for(k=0; k<getlength(var); k++)
3796 newints[io_techlayerfixes[j].arrangement[k]] =
3797 ((INTBIG *)var->addr)[k];
3798 (void)setvalkey((INTBIG)tech, VTECHNOLOGY, io_techlayervariables[i].key,
3799 (INTBIG)newints, (var->type&VTYPE)|VISARRAY|(tech->layercount<<VLENGTHSH));
3800 efree((CHAR *)newints);
3801 }
3802 }
3803 continue;
3804 }
3805
3806 /* unable to fix: issue a warning */
3807 ttyputmsg(_("Warning: library %s has %s in technology %s which are inconsistent"),
3808 lib->libname, TRANSLATE(io_techlayervariables[i].meaning), tech->techname);
3809 if (io_techlayervariables[i].variabletype != VARTYPELAYERNONDRC)
3810 {
3811 if (!factorywarned)
3812 {
3813 factorywarned = TRUE;
3814 ttyputmsg(_("Should do a 'Factory Reset' of design rules in 'DRC Rules' dialog"));
3815 }
3816 }
3817 }
3818 }
3819 }
3820
io_fixrtree(RTNODE * rtree)3821 void io_fixrtree(RTNODE *rtree)
3822 {
3823 REGISTER INTBIG i;
3824 REGISTER GEOM *geom;
3825 REGISTER RTNODE *subrt;
3826
3827 if (rtree->total <= 0) return;
3828 if (rtree->flag != 0)
3829 {
3830 geom = (GEOM *)rtree->pointers[0];
3831 rtree->lowx = geom->lowx; rtree->highx = geom->highx;
3832 rtree->lowy = geom->lowy; rtree->highy = geom->highy;
3833 for(i=1; i<rtree->total; i++)
3834 {
3835 geom = (GEOM *)rtree->pointers[i];
3836 if (geom->lowx < rtree->lowx) rtree->lowx = geom->lowx;
3837 if (geom->highx > rtree->highx) rtree->highx = geom->highx;
3838 if (geom->lowy < rtree->lowy) rtree->lowy = geom->lowy;
3839 if (geom->highy > rtree->highy) rtree->highy = geom->highy;
3840 }
3841 } else
3842 {
3843 subrt = (RTNODE *)rtree->pointers[0];
3844 io_fixrtree(subrt);
3845 rtree->lowx = subrt->lowx; rtree->highx = subrt->highx;
3846 rtree->lowy = subrt->lowy; rtree->highy = subrt->highy;
3847 for(i=1; i<rtree->total; i++)
3848 {
3849 subrt = (RTNODE *)rtree->pointers[i];
3850 io_fixrtree(subrt);
3851 if (subrt->lowx < rtree->lowx) rtree->lowx = subrt->lowx;
3852 if (subrt->highx > rtree->highx) rtree->highx = subrt->highx;
3853 if (subrt->lowy < rtree->lowy) rtree->lowy = subrt->lowy;
3854 if (subrt->highy > rtree->highy) rtree->highy = subrt->highy;
3855 }
3856 }
3857 }
3858
3859 /*
3860 * routine to convert port names that have changed (specifically those
3861 * in the Schematics technology). Given the port name on a node proto,
3862 * returns the correct port (or NOPORTPROTO if not known).
3863 */
io_convertoldportname(CHAR * portname,NODEPROTO * np)3864 PORTPROTO *io_convertoldportname(CHAR *portname, NODEPROTO *np)
3865 {
3866 REGISTER PORTPROTO *pp;
3867 REGISTER INTBIG len;
3868 CHAR truename[300];
3869
3870 if (np->primindex == 0) return(NOPORTPROTO);
3871 if (np == sch_sourceprim || np == sch_meterprim)
3872 {
3873 if (namesame(portname, x_("top")) == 0)
3874 return(np->firstportproto);
3875 if (namesame(portname, x_("bottom")) == 0)
3876 return(np->firstportproto->nextportproto);
3877 }
3878 if (np == sch_twoportprim)
3879 {
3880 if (namesame(portname, x_("upperleft")) == 0)
3881 return(np->firstportproto);
3882 if (namesame(portname, x_("lowerleft")) == 0)
3883 return(np->firstportproto->nextportproto);
3884 if (namesame(portname, x_("upperright")) == 0)
3885 return(np->firstportproto->nextportproto->nextportproto);
3886 if (namesame(portname, x_("lowerright")) == 0)
3887 return(np->firstportproto->nextportproto->nextportproto->nextportproto);
3888 }
3889
3890 /* some technologies switched from ports ending in "-bot" to the ending "-bottom" */
3891 len = estrlen(portname) - 4;
3892 if (len > 0 && namesame(&portname[len], x_("-bot")) == 0)
3893 {
3894 estrcpy(truename, portname);
3895 estrcat(truename, x_("tom"));
3896 pp = getportproto(np, truename);
3897 if (pp != NOPORTPROTO) return(pp);
3898 }
3899 return(NOPORTPROTO);
3900 }
3901
3902 /*
3903 * Routine to determine the area of cell "np" that is to be printed.
3904 * Returns true if the area cannot be determined.
3905 */
io_getareatoprint(NODEPROTO * np,INTBIG * lx,INTBIG * hx,INTBIG * ly,INTBIG * hy,BOOLEAN reduce)3906 BOOLEAN io_getareatoprint(NODEPROTO *np, INTBIG *lx, INTBIG *hx, INTBIG *ly, INTBIG *hy, BOOLEAN reduce)
3907 {
3908 REGISTER INTBIG wid, hei, *curstate;
3909 INTBIG hlx, hhx, hly, hhy;
3910 REGISTER NODEPROTO *onp;
3911
3912 curstate = io_getstatebits();
3913 us_fullview(np, lx, hx, ly, hy);
3914
3915 /* extend it and make it square */
3916 wid = *hx - *lx;
3917 hei = *hy - *ly;
3918 if (reduce)
3919 {
3920 *lx -= wid/8; *hx += wid/8;
3921 *ly -= hei/8; *hy += hei/8;
3922 us_squarescreen(el_curwindowpart, NOWINDOWPART, FALSE, lx, hx, ly, hy, 0);
3923 }
3924
3925 if ((curstate[0]&PLOTFOCUS) != 0)
3926 {
3927 if ((curstate[0]&PLOTFOCUSDPY) != 0)
3928 {
3929 *lx = el_curwindowpart->screenlx;
3930 *hx = el_curwindowpart->screenhx;
3931 *ly = el_curwindowpart->screenly;
3932 *hy = el_curwindowpart->screenhy;
3933 } else
3934 {
3935 onp = (NODEPROTO *)asktool(us_tool, x_("get-highlighted-area"),
3936 (INTBIG)&hlx, (INTBIG)&hhx, (INTBIG)&hly, (INTBIG)&hhy);
3937 if (onp == NONODEPROTO)
3938 ttyputerr(_("Warning: no highlighted area; printing entire cell")); else
3939 {
3940 if (hhx == hlx || hhy == hly)
3941 {
3942 ttyputerr(_("Warning: no highlighted area; highlight area and reissue command"));
3943 return(TRUE);
3944 }
3945 *lx = hlx; *hx = hhx;
3946 *ly = hly; *hy = hhy;
3947 }
3948 }
3949 }
3950 return(FALSE);
3951 }
3952
3953 /******************** LAYER ORDERING FOR GRAPHIC COPY/PRINT ********************/
3954
io_setuptechorder(TECHNOLOGY * tech)3955 INTBIG io_setuptechorder(TECHNOLOGY *tech)
3956 {
3957 REGISTER INTBIG i, j, k, l, m, *neworder, newamount;
3958 REGISTER INTBIG *layers;
3959 INTBIG order[LFNUMLAYERS];
3960 REGISTER VARIABLE *var;
3961
3962 /* determine order of overlappable layers in current technology */
3963 io_maxlayers = 0;
3964 i = tech->layercount;
3965 var = getval((INTBIG)tech, VTECHNOLOGY, VINTEGER|VISARRAY,
3966 x_("TECH_layer_function"));
3967 if (var != NOVARIABLE)
3968 {
3969 layers = (INTBIG *)var->addr;
3970 for(j=0; j<LFNUMLAYERS; j++)
3971 order[j] = layerfunctionheight(j);
3972 for(j=0; j<LFNUMLAYERS; j++)
3973 {
3974 for(k=0; k<LFNUMLAYERS; k++)
3975 {
3976 if (order[k] != j) continue;
3977 for(l=0; l<i; l++)
3978 {
3979 if ((layers[l]&LFTYPE) != k) continue;
3980 if (io_maxlayers >= io_mostlayers)
3981 {
3982 newamount = io_mostlayers * 2;
3983 if (newamount <= 0) newamount = 10;
3984 if (newamount < io_maxlayers) newamount = io_maxlayers;
3985 neworder = (INTBIG *)emalloc(newamount * SIZEOFINTBIG, io_tool->cluster);
3986 if (neworder == 0) return(io_maxlayers);
3987 for(m=0; m<io_maxlayers; m++)
3988 neworder[m] = io_overlaporder[m];
3989 if (io_mostlayers > 0) efree((CHAR *)io_overlaporder);
3990 io_overlaporder = neworder;
3991 io_mostlayers = newamount;
3992 }
3993 io_overlaporder[io_maxlayers++] = l;
3994 }
3995 break;
3996 }
3997 }
3998 }
3999 return(io_maxlayers);
4000 }
4001
4002 /*
4003 * Routine to return the layer in plotting position "i" (from 0 to the value returned
4004 * by "io_setuptechorder" - 1).
4005 */
io_nextplotlayer(INTBIG i)4006 INTBIG io_nextplotlayer(INTBIG i)
4007 {
4008 return(io_overlaporder[i]);
4009 }
4010
4011 /******************** MATH HELPERS ********************/
4012
4013 /*
4014 * This routine is used by "ioedifo.c" and "routmaze.c".
4015 */
io_compute_center(INTBIG xc,INTBIG yc,INTBIG x1,INTBIG y1,INTBIG x2,INTBIG y2,INTBIG * cx,INTBIG * cy)4016 void io_compute_center(INTBIG xc, INTBIG yc, INTBIG x1, INTBIG y1,
4017 INTBIG x2, INTBIG y2, INTBIG *cx, INTBIG *cy)
4018 {
4019 int r, dx, dy, a1, a2, a;
4020 double pie, theta, radius, Dx, Dy;
4021
4022 /* reconstruct angles to p1 and p2 */
4023 Dx = x1 - xc;
4024 Dy = y1 - yc;
4025 radius = sqrt(Dx * Dx + Dy * Dy);
4026 r = rounddouble(radius);
4027 a1 = (int)io_calc_angle(r, (double)(x1 - xc), (double)(y1 - yc));
4028 a2 = (int)io_calc_angle(r, (double)(x2 - xc), (double)(y2 - yc));
4029 if (a1 < a2) a1 += 3600;
4030 a = (a1 + a2) >> 1;
4031 pie = acos(-1.0);
4032 theta = (double) a *pie / 1800.0; /* in radians */
4033 Dx = radius * cos(theta);
4034 Dy = radius * sin(theta);
4035 dx = rounddouble(Dx);
4036 dy = rounddouble(Dy);
4037 *cx = xc + dx;
4038 *cy = yc + dy;
4039 }
4040
io_calc_angle(double r,double dx,double dy)4041 double io_calc_angle(double r, double dx, double dy)
4042 {
4043 double ratio, a1, a2;
4044
4045 ratio = 1800.0 / EPI;
4046 a1 = acos(dx/r) * ratio;
4047 a2 = asin(dy/r) * ratio;
4048 if (a2 < 0.0) return(3600.0 - a1);
4049 return(a1);
4050 }
4051