1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: ioedifi.c
6 * Input/output tool: EDIF 2 0 0 netlist reader
7 * Written by: Glen Lawson
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 #define IGNORESTRINGSWITHSQUAREBRACKETS 1 /* uncomment to ignore strings starting with "[" */
33 #define SLOPDISTANCE 1 /* allow connections when this many lambda away (0 to force exact placement) */
34
35 /*
36 * Notes (11/12/92):
37 * I have tried EDIF files from CADENCE and VALID only.
38 * Does not fully support portbundles
39 * Multiple ports of the same name are named port_x (x is 1 to n duplicate)
40 * Keywords such as ARRAY have unnamed parameters, ie (array (name..) 5 6)
41 * this is handled in the io_edprocess_integer function called by io_edget_keyword,
42 * this is a hack to fix this problem, a real table driven parser should be used.
43 * Improved (3/9/92) by Steven Rubin:
44 * handle progress dialogs during input
45 * changed "malloc" and "free" to "emalloc" and "efree"
46 * memory allocation bug in "io_edpop_stack()" caused crash when current technology gas GDS layers
47 * gml (1/94)
48 * Use circle arcs instead of splines.
49 * Support text justifications and text height
50 * Better NAME/RENAME/STRINGDISPLAY/ANNOTATE text handling.
51 * gml (3/94)
52 * ANSI prototypes
53 * gml (9/94)
54 * Changed arcs to simple polygons plus ARC attribute
55 * gml (12/94)
56 * Can read NETLIST views
57 */
58
59 #include "config.h"
60 #include "global.h"
61 #include "egraphics.h"
62 #include "efunction.h"
63 #include "database.h"
64 #include "edialogs.h"
65 #include "tecgen.h"
66 #include "tecart.h"
67 #include "tecschem.h"
68 #include "eio.h"
69 #include "network.h"
70 #include "usr.h"
71 #include <math.h>
72
73 /* some length defines */
74 #define LINE 4096
75 #define WORD 4096
76 #define MAXLAYERS 256
77
78 #define LONGJMPEOF 1 /* error: "Unexpected end-of-file" */
79 #define LONGJMPNOMEM 2 /* error: "No memory" */
80 #define LONGJMPPTMIS 3 /* error: "Point list mismatch" */
81 #define LONGJMPNOLIB 4 /* error: "Could not create library" */
82 #define LONGJMPNOINT 5 /* error: "No integer value" */
83 #define LONGJMPILLNUM 6 /* error: "Illegal number value" */
84 #define LONGJMPNOMANT 7 /* error: "No matissa value" */
85 #define LONGJMPNOEXP 8 /* error: "No exponent value" */
86 #define LONGJMPILLNAME 9 /* error: "Illegal name" */
87 #define LONGJMPILLDELIM 10 /* error: "Illegal delimeter" */
88
89 typedef enum
90 {
91 UPPERLEFT,
92 UPPERCENTER,
93 UPPERRIGHT,
94 CENTERLEFT,
95 CENTERCENTER,
96 CENTERRIGHT,
97 LOWERLEFT,
98 LOWERCENTER,
99 LOWERRIGHT
100 } TEXTJUST;
101
102 /* generic defines */
103 static CHAR *DELIMETERS = x_(" \t\r\n=.:;'()}\"");
104
105 /* name table for layers */
106 #define NONAMETABLE ((NAMETABLE_PTR)0)
107 typedef struct
108 {
109 CHAR *original; /* the original MASK layer */
110 CHAR *replace; /* the replacement layer */
111 NODEPROTO *node; /* the basic electric node */
112 ARCPROTO *arc; /* the basic arc type */
113 int textheight; /* default text height */
114 TEXTJUST justification; /* default justification */
115 int visible; /* layer is visible */
116 } NAMETABLE, *NAMETABLE_PTR;
117
118 /* the following is a table of EDIF keywords, and functions */
119 typedef enum
120 {
121 KUNKNOWN,
122 KINIT,
123 KANNOTATE,
124 KARC,
125 KARRAY,
126 KAUTHOR,
127 KBOOLEAN,
128 KBORDERWIDTH,
129 KBOUNDINGBOX,
130 KCELL,
131 KCELLREF,
132 KCELLTYPE,
133 KCIRCLE,
134 KCOLOR,
135 KCONTENTS,
136 KCOMMENT,
137 KCOMMENTGRAPHICS,
138 KCONNECTLOCATION,
139 KCORNERTYPE,
140 KCURVE,
141 KDATAORIGIN,
142 KDCFANOUTLOAD,
143 KDCMAXFANOUT,
144 KDELTA,
145 KDESIGN,
146 KDESIGNATOR,
147 KDIRECTION,
148 KDISPLAY,
149 KDOT,
150 KEDIF,
151 KEDIFLEVEL,
152 KEDIFVERSION,
153 KENDTYPE,
154 KEXTERNAL,
155 KFABRICATE,
156 KFALSE,
157 KFIGURE,
158 KFIGUREGROUP,
159 KFIGUREGROUPOVERRIDE,
160 KFIGUREGROUPREF,
161 KFILLPATTERN,
162 KGRIDMAP,
163 KINSTANCE,
164 KINSTANCEREF,
165 KINTEGER,
166 KINTERFACE,
167 KJOINED,
168 KJUSTIFY,
169 KKEYWORDDISPLAY,
170 KEDIFKEYMAP,
171 KEDIFKEYLEVEL,
172 KLIBRARY,
173 KLIBRARYREF,
174 KLISTOFNETS,
175 KLISTOFPORTS,
176 KLOGICREF,
177 KMEMBER,
178 KMUSTJOIN,
179 KNAME,
180 KNET,
181 KNETBUNDLE,
182 KNETREF,
183 KNUMBER,
184 KNUMBERDEFINITION,
185 KORIENTATION,
186 KORIGIN,
187 KOWNER,
188 KPAGE,
189 KPAGESIZE,
190 KPARAMETER,
191 KPATH,
192 KPATHWIDTH,
193 KPOINT,
194 KPOINTLIST,
195 KPOLYGON,
196 KPORT,
197 KPORTBUNDLE,
198 KPORTIMPLEMENTATION,
199 KPORTINSTANCE,
200 KPORTLIST,
201 KPORTREF,
202 KPROGRAM,
203 KPROPERTY,
204 KPROPERTYDISPLAY,
205 KPT,
206 KNAMEDEF,
207 KOPENSHAPE,
208 KRECTANGLE,
209 KRENAME,
210 KSCALE,
211 KSCALEDINTEGER,
212 KSCALEX,
213 KSCALEY,
214 KSITE,
215 KSHAPE,
216 KSTATUS,
217 KSTRING,
218 KSTRINGDISPLAY,
219 KSYMBOL,
220 KTECHNOLOGY,
221 KTEXTHEIGHT,
222 KTIMESTAMP,
223 KTRANSFORM,
224 KTRUE,
225 KUNIT,
226 KUSERDATA,
227 KVERSION,
228 KVIEW,
229 KVIEWLIST,
230 KVIEWREF,
231 KVIEWTYPE,
232 KVISIBLE,
233 KWEAKJOINED,
234 KWRITTEN
235 } KSTATE;
236
237 #define KNULL ((KSTATE *) 0)
238 typedef struct
239 {
240 CHAR *name; /* the name of the keyword */
241 INTBIG (*func)(void); /* the function to execute */
242 KSTATE next; /* the next state, if any */
243 KSTATE *state; /* edif state */
244 } EDIFKEY, *EDIFKEY_PTR;
245 #define NOEDIFKEY ((EDIFKEY_PTR) 0)
246
247 /* Edif viewtypes ... */
248 typedef enum
249 {
250 VNULL,
251 VBEHAVIOR,
252 VDOCUMENT,
253 VGRAPHIC,
254 VLOGICMODEL,
255 VMASKLAYOUT,
256 VNETLIST,
257 VPCBLAYOUT,
258 VSCHEMATIC,
259 VSTRANGER,
260 VSYMBOLIC,
261 VSYMBOL /* not a real EDIF view, but electric has one */
262 } VTYPES;
263
264 /* Edif geometry types ... */
265 typedef enum
266 {
267 GUNKNOWN,
268 GRECTANGLE,
269 GPOLYGON,
270 GSHAPE,
271 GOPENSHAPE,
272 GTEXT,
273 GPATH,
274 GINSTANCE,
275 GCIRCLE,
276 GARC,
277 GPIN,
278 GNET,
279 GBUS
280 } GTYPES;
281
282 /* 8 standard orientations */
283 typedef enum
284 {
285 OUNKNOWN,
286 OR0,
287 OR90,
288 OR180,
289 OR270,
290 OMX,
291 OMY,
292 OMYR90,
293 OMXR90
294 } OTYPES;
295
296 typedef struct _ept
297 {
298 int x, y;
299 struct _ept *nextpt;
300 } EPT, *EPT_PTR;
301 #define NOEPT ((EPT_PTR)0)
302
303 typedef enum {INOUT, INPUTE, OUTPUTE} EDPORTDIR;
304
305 #define INCH (10*el_curlib->lambda[io_edifgbl.technology->techindex])
306
307 typedef struct _edport
308 {
309 CHAR *name;
310 CHAR *reference;
311 EDPORTDIR direction;
312 int arrayx, arrayy;
313 struct _edport *next;
314 } EDPORT, *EDPORT_PTR;
315 #define NOEDPORT ((EDPORT_PTR)0)
316
317 typedef struct _ednetport
318 {
319 NODEINST *ni; /* unique node port is attached to */
320 PORTPROTO *pp; /* port type (no portarc yet) */
321 int member; /* member for an array */
322 struct _ednetport *next; /* next common to a net */
323 } EDNETPORT, *EDNETPORT_PTR;
324 #define NOEDNETPORT ((EDNETPORT_PTR)0)
325
326 typedef enum
327 {
328 EVUNKNOWN,
329 EVCADENCE,
330 EVVALID,
331 EVSYNOPSYS,
332 EVMENTOR,
333 EVVIEWLOGIC
334 } EDVENDOR;
335
336 #define MAXSHEETS 6
337 typedef enum
338 {
339 SHEET_ASIZE = 0,
340 SHEET_BSIZE = 1,
341 SHEET_CSIZE = 2,
342 SHEET_DSIZE = 3,
343 SHEET_ESIZE = 4,
344 SHEET_INFSIZE = 5
345 } SHEET_SIZE;
346
347 typedef enum
348 {
349 PUNKNOWN,
350 PSTRING,
351 PINTEGER,
352 PNUMBER
353 } PROPERTY_TYPE;
354
355 typedef struct _edproperty
356 {
357 CHAR *name;
358 union
359 {
360 int integer;
361 float number;
362 CHAR *string;
363 } val;
364 PROPERTY_TYPE type;
365 struct _edproperty *next;
366 } EDPROPERTY, *EDPROPERTY_PTR;
367 #define NOEDPROPERTY ((EDPROPERTY_PTR)0)
368
369 /* edifgbl declaration */
370 typedef struct
371 {
372 /* general information variables */
373 FILE *edif_file; /* the input file */
374 jmp_buf env; /* longjmp return */
375
376 /* view information ... */
377 int pageno; /* the schematic page number */
378 VTYPES active_view; /* indicates we are in a NETLIST view */
379 int drawing_number; /* the current drawing number */
380 int p_ref, c_ref; /* peripheral and core reference names */
381 EDVENDOR vendor; /* the current vendor type */
382
383 /* parser variables ... */
384 KSTATE state; /* the current parser state */
385 int lineno; /* the current line number */
386 CHAR buffer[LINE+1]; /* the read buffer */
387 CHAR *pos; /* the position within the buffer */
388 int ignoreblock; /* no update flag */
389 CHAR *delimeters; /* parsing delimeters for edif */
390 int errors, warnings; /* load status */
391
392 /* electric context data ... */
393 LIBRARY *library; /* the new library */
394 TECHNOLOGY *technology; /* the active technology */
395 NODEPROTO *current_cell; /* the current active cell */
396 NODEINST *current_node; /* the current active instance */
397 ARCINST *current_arc; /* the current active arc */
398 NODEPROTO *figure_group; /* the current figure group node */
399 ARCPROTO *arc_type; /* the current (if exists) arc type */
400 NODEPROTO *proto; /* the cellRef type */
401 PORTPROTO *current_port; /* the current port proto */
402
403 /* general geometry information ... */
404 GTYPES geometry; /* the current geometry type */
405 EPT *points; /* the list of points */
406 EPT *lastpt; /* the end of the list */
407 int pt_count; /* the count of points */
408 OTYPES orientation; /* the orientation of the structure */
409 EDPORTDIR direction; /* port direction */
410
411 /* geometric path constructors ... */
412 int path_width; /* the width of the path */
413 int extend_corner; /* extend path corner flag */
414 int extend_end; /* extend path end flag */
415
416 /* array variables ... */
417 int isarray; /* set if truely an array */
418 int arrayx, arrayy; /* the bounds of the array */
419 int deltaxX, deltaxY; /* offsets in x and y for an X increment */
420 int deltayX, deltayY; /* offsets in x and y for an Y increment */
421 int deltapts; /* which offset flag */
422 int memberx, membery; /* the element of the array */
423
424 /* text variables ... */
425 CHAR string[LINE+1]; /* Text string */
426 int textheight; /* the current default text height */
427 TEXTJUST justification; /* the current text justificaton */
428 int visible; /* is stringdisplay visible */
429 struct { /* save block for name and rename strings */
430 CHAR string[LINE+1]; /* the saved string, if NULL not saved */
431 EPT *points; /* origin x and y */
432 int pt_count; /* count of points (usually 1) */
433 int textheight; /* the height of text */
434 int visible; /* visiblity of the text */
435 TEXTJUST justification; /* justification of the text */
436 OTYPES orientation; /* orientation of the text */
437 } save_text;
438
439 /* technology data ... */
440 double scale; /* scaling value */
441 double dbunit; /* database units */
442 double meters; /* per number of meters */
443 double val1, val2; /* temporary storage */
444
445 /* current name and rename of EDIF objects ... */
446 CHAR cell_reference[WORD+1]; /* the current cell name */
447 CHAR cell_name[WORD+1]; /* the current cell name (original) */
448 CHAR port_reference[WORD+1]; /* the current port name */
449 CHAR port_name[WORD+1]; /* the current port name (original) */
450 CHAR instance_reference[WORD+1]; /* the current instance name */
451 CHAR instance_name[WORD+1]; /* the current instance name (original) */
452 CHAR bundle_reference[WORD+1]; /* the current bundle name */
453 CHAR bundle_name[WORD+1]; /* the current bundle name (original) */
454 CHAR net_reference[WORD+1]; /* the current net name */
455 CHAR net_name[WORD+1]; /* the current net name (original) */
456 CHAR property_reference[WORD+1]; /* the current property name */
457 CHAR property_name[WORD+1]; /* the current property name (original) */
458
459 PROPERTY_TYPE ptype; /* the type of property */
460 union {
461 CHAR *string; /* string buffer */
462 int integer; /* integer buffer */
463 float number; /* number buffer */
464 } pval;
465
466 CHAR name[WORD+1]; /* the name of the object */
467 CHAR original[WORD+1]; /* the original name of the object */
468
469 /* layer or figure information ... */
470 int layer_ptr; /* pointer to layer table entry */
471 NAMETABLE_PTR nametbl[MAXLAYERS]; /* the current name mapping table */
472 NAMETABLE_PTR cur_nametbl; /* the current name table entry */
473
474 /* cell name lookup (from rename) */
475 NAMETABLE_PTR *celltbl; /* the cell lookup table */
476 int celltbl_cnt; /* the count of entries in the cell table */
477 int celltbl_sze; /* maximum size of the table */
478
479 /* port data for port exporting */
480 EDPORT_PTR ports; /* active port list */
481 EDPORT_PTR free_ports; /* the list of free ports */
482
483 /* property data for all objects */
484 EDPROPERTY_PTR properties; /* active property list */
485 EDPROPERTY_PTR free_properties; /* the list of free properties */
486
487 /* net constructors */
488 EDNETPORT_PTR firstnetport; /* the list of ports on a net */
489 EDNETPORT_PTR lastnetport; /* the last in the list on a net */
490 EDNETPORT_PTR free_netports; /* the list of free ports */
491
492 /* view NETLIST layout */
493 SHEET_SIZE sheet_size; /* the size of the target sheet */
494 int sh_xpos, sh_ypos; /* current sheet position */
495 int sh_offset; /* next x offset */
496 int ipos, bpos, opos; /* current position pointers */
497 } EDIFGBL;
498
499 BOOLEAN io_edgblinited = FALSE;
500
501 static EDIFGBL io_edifgbl;
502
503 /* prototypes for local routines */
504 static INTBIG io_edload_edif(INTBIG key_count, EDIFKEY_PTR keywords);
505 static INTBIG io_edfreesavedptlist(void);
506 static double io_edgetnumber(void);
507 static INTBIG io_edcheck_name(void);
508 static INTBIG io_edpop_stack(void);
509 static void io_edprocess_integer(INTBIG value);
510 static INTSML io_edgetrot(OTYPES orientation);
511 static INTSML io_edgettrans(OTYPES orientation);
512 static int io_edcompare_name(const void *name1, const void *name2);
513 static INTBIG io_edis_integer(CHAR *buffer);
514 static CHAR *io_edget_keyword(CHAR *buffer);
515 static CHAR *io_edget_token(CHAR *buffer, CHAR idelim);
516 static CHAR *io_edpos_token(void);
517 static BOOLEAN io_edget_line(CHAR *line, INTBIG limit, FILE *file);
518 static void io_edget_delim(CHAR delim);
519 static INTBIG io_edallocport(void);
520 static INTBIG io_edallocproperty(CHAR *name, PROPERTY_TYPE type, int integer,
521 float number, CHAR *string);
522 static INTBIG io_edallocnetport(void);
523 static void io_edeq_of_a_line(double sx, double sy, double ex, double ey, double *A, double *B, double *C);
524 static INTBIG io_eddetermine_intersection(double A[2], double B[2], double C[2], double *x, double *y);
525 static void io_ededif_arc(INTBIG x[3], INTBIG y[3], INTBIG *xc, INTBIG *yc, INTBIG *r, double *so,
526 double *ar, INTBIG *rot, INTBIG *trans);
527 static NODEPROTO *io_edmakeiconcell(PORTPROTO *fpp, CHAR *iconname, CHAR *pt, LIBRARY *lib);
528 static void io_ednamearc(ARCINST *ai);
529 static INTBIG io_edfindport(NODEPROTO *cell, INTBIG x, INTBIG y, ARCPROTO *ap, NODEINST *nis[],
530 PORTPROTO *pps[]);
531 static INTBIG io_edfindport_geom(NODEPROTO *cell, INTBIG x, INTBIG y, ARCPROTO *ap,
532 NODEINST *nis[], PORTPROTO *pps[], ARCINST **ai);
533 static void io_edfreenetports(void);
534 static INTBIG io_ediftextsize(INTBIG textheight);
535 static NODEINST *io_edifiplacepin(NODEPROTO *np, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy,
536 INTBIG trans, INTBIG angle, NODEPROTO *parent);
537
538 /* keyword parser entry points, only these keywords are supported by this parser,
539 if you need more, add them. Each entry point can have an exit point in the
540 function io_edpop_stack. This is processed when ')' is encountered in the EDIF
541 file.
542 */
543 static INTBIG io_ednoop(void);
544 static INTBIG io_edtechnology(void);
545 static INTBIG io_edfabricate(void);
546 static INTBIG io_edpage(void);
547 static INTBIG io_edfigure(void);
548 static INTBIG io_edfigureGroupOverride(void);
549 static INTBIG io_edscale(void);
550 static INTBIG io_edendType(void);
551 static INTBIG io_edcornerType(void);
552 static INTBIG io_edstringDisplay(void);
553 static INTBIG io_edtrue(void);
554 static INTBIG io_edfalse(void);
555 static INTBIG io_edgetlayer(void);
556 static INTBIG io_edpointList(void);
557 static INTBIG io_edpoint(void);
558 static INTBIG io_edjustify(void);
559 static INTBIG io_edtextHeight(void);
560 static INTBIG io_edpt(void);
561 static INTBIG io_edorientation(void);
562 static INTBIG io_edpathWidth(void);
563 static INTBIG io_edrectangle(void);
564 static INTBIG io_edcircle(void);
565 static INTBIG io_edpath(void);
566 static INTBIG io_edpolygon(void);
567 static INTBIG io_edopenShape(void);
568 static INTBIG io_edfreeptlist(void);
569 static INTBIG io_edlibrary(void);
570 static INTBIG io_eddesign(void);
571 static INTBIG io_edcell(void);
572 static INTBIG io_edview(void);
573 static INTBIG io_edviewType(void);
574 static INTBIG io_edcontents(void);
575 static INTBIG io_edport(void);
576 static INTBIG io_eddirection(void);
577 static INTBIG io_edinstance(void);
578 static INTBIG io_edarray(void);
579 static INTBIG io_eddelta(void);
580 static INTBIG io_edcellRef(void);
581 static INTBIG io_edproperty(void);
582 static INTBIG io_ednet(void);
583 static INTBIG io_ednetBundle(void);
584 static INTBIG io_edjoined(void);
585 static INTBIG io_edportRef(void);
586 static INTBIG io_edinstanceRef(void);
587 static INTBIG io_edmember(void);
588 static INTBIG io_edname(void);
589 static INTBIG io_edrename(void);
590 static INTBIG io_edboundingBox(void);
591 static INTBIG io_edsymbol(void);
592 static INTBIG io_edportImplementation(void);
593 static INTBIG io_edconnectLocation(void);
594 static INTBIG io_eddot(void);
595 static INTBIG io_edprogram(void);
596 static INTBIG io_edunit(void);
597 static INTBIG io_edinteger(void);
598 static INTBIG io_ednumber(void);
599 static INTBIG io_edstring(void);
600 static INTBIG io_edinterface(void);
601
602 /* Parser keyword state tables, only some are provided, others are simply incomplete.
603 If you have time, please feel free to complete these keyword tables and the following
604 parse array. Note that a bad state does not cause the parser to quit, the action is
605 still executed.
606 */
607 static KSTATE Sarray[] = {KINSTANCE, KPORT, KNET, KUNKNOWN};
608 static KSTATE Sauthor[] = {KWRITTEN, KUNKNOWN};
609 static KSTATE SboundingBox[] = {KSYMBOL, KCONTENTS, KUNKNOWN};
610 static KSTATE Scell[] = {KEXTERNAL, KLIBRARY, KUNKNOWN};
611 static KSTATE ScellRef[] = {KDESIGN, KVIEWREF, KINSTANCE, KUNKNOWN};
612 static KSTATE ScellType[] = {KCELL, KUNKNOWN};
613 static KSTATE Scontents[] = {KVIEW, KUNKNOWN};
614 static KSTATE Sdesign[] = {KEDIF, KUNKNOWN};
615 static KSTATE Sdirection[] = {KPORT, KUNKNOWN};
616 static KSTATE Sedif[] = {KINIT, KUNKNOWN};
617 static KSTATE SedifLevel[] = {KEDIF, KEXTERNAL, KLIBRARY, KUNKNOWN};
618 static KSTATE SedifVersion[] = {KEDIF, KUNKNOWN};
619 static KSTATE Sinstance[] = {KCONTENTS, KPAGE, KPORTIMPLEMENTATION, KCOMMENTGRAPHICS, KUNKNOWN};
620 static KSTATE SinstanceRef[] = {KINSTANCEREF, KPORTREF, KUNKNOWN};
621 static KSTATE Sinterface[] = {KVIEW, KUNKNOWN};
622 static KSTATE Sjoined[] = {KINTERFACE, KNET, KMUSTJOIN, KWEAKJOINED, KUNKNOWN};
623 static KSTATE SkeywordMap[] = {KEDIF, KUNKNOWN};
624 static KSTATE Slibrary[] = {KEDIF, KUNKNOWN};
625 static KSTATE SlibraryRef[] = {KCELLREF, KFIGUREGROUPREF, KLOGICREF, KUNKNOWN};
626 static KSTATE SlistOfNets[] = {KNETBUNDLE, KUNKNOWN};
627 static KSTATE Snet[] = {KCONTENTS, KPAGE, KLISTOFNETS, KUNKNOWN};
628 static KSTATE SnetBundle[] = {KCONTENTS, KPAGE, KUNKNOWN};
629 static KSTATE SnumberDefinition[] = {KTECHNOLOGY, KUNKNOWN};
630 static KSTATE Sport[] = {KINTERFACE, KLISTOFPORTS, KUNKNOWN};
631 static KSTATE Sscale[] = {KNUMBERDEFINITION, KUNKNOWN};
632 static KSTATE Sstatus[] = {KCELL, KDESIGN, KEDIF, KEXTERNAL, KLIBRARY, KVIEW, KUNKNOWN};
633 static KSTATE Ssymbol[] = {KINTERFACE, KUNKNOWN};
634 static KSTATE Stechnology[] = {KEXTERNAL, KLIBRARY, KUNKNOWN};
635 static KSTATE Stimestamp[] = {KWRITTEN, KUNKNOWN};
636 static KSTATE Sunit[] = {KPARAMETER, KPROPERTY, KSCALE, KUNKNOWN};
637 static KSTATE Sview[] = {KCELL, KUNKNOWN};
638 static KSTATE SviewRef[] = {KINSTANCE, KINSTANCEREF, KNETREF, KPORTREF, KSITE, KVIEWLIST, KUNKNOWN};
639 static KSTATE SviewType[] = {KVIEW, KUNKNOWN};
640 static KSTATE Swritten[] = {KSTATUS, KUNKNOWN};
641
642 /* To add a new keyword, insert into this sorted list and into the enumerated keyword
643 list in ioedif.h. If no action is required, just use the io_ednoop as the action
644 routine. If some action is required, add a new function. Note that all operations
645 are dependent on the current state. If a keyword is correct, but the required state
646 table is not, add it to the above data structure (_kstate). Or make it non-state
647 dependent with a KNULL in the last field.
648 */
649 static EDIFKEY edif_keywords[] =
650 {
651 {x_("annotate"), io_ednoop, KANNOTATE, KNULL},
652 {x_("arc"), io_ednoop, KARC, KNULL},
653 {x_("array"), io_edarray, KARRAY, Sarray},
654 {x_("author"), io_ednoop, KAUTHOR, Sauthor},
655 {x_("boolean"), io_ednoop, KBOOLEAN, KNULL},
656 {x_("borderWidth"), io_ednoop, KBORDERWIDTH, KNULL},
657 {x_("boundingBox"), io_edboundingBox, KBOUNDINGBOX, SboundingBox},
658 {x_("cell"), io_edcell, KCELL, Scell },
659 {x_("cellRef"), io_edcellRef, KCELLREF, ScellRef},
660 {x_("cellType"), io_ednoop, KCELLTYPE, ScellType},
661 {x_("circle"), io_edcircle, KCIRCLE, KNULL},
662 {x_("color"), io_ednoop, KCOLOR, KNULL},
663 {x_("comment"), io_ednoop, KCOMMENT, KNULL},
664 {x_("commentGraphics"), io_ednoop, KCOMMENTGRAPHICS, KNULL},
665 {x_("connectLocation"), io_edconnectLocation, KCONNECTLOCATION, KNULL},
666 {x_("contents"), io_edcontents, KCONTENTS, Scontents},
667 {x_("cornerType"), io_edcornerType, KCORNERTYPE, KNULL},
668 {x_("curve"), io_ednoop, KCURVE, KNULL},
669 {x_("dataOrigin"), io_ednoop, KDATAORIGIN, KNULL},
670 {x_("dcFanoutLoad"), io_ednoop, KDCFANOUTLOAD, KNULL},
671 {x_("dcMaxFanout"), io_ednoop, KDCMAXFANOUT, KNULL},
672 {x_("delta"), io_eddelta, KDELTA, KNULL},
673 {x_("design"), io_eddesign, KDESIGN, Sdesign},
674 {x_("designator"), io_ednoop, KDESIGNATOR, KNULL},
675 {x_("direction"), io_eddirection, KDIRECTION, Sdirection},
676 {x_("display"), io_edfigure, KDISPLAY, KNULL},
677 {x_("dot"), io_eddot, KDOT, KNULL},
678 {x_("e"), io_ednoop, KSCALEDINTEGER, KNULL},
679 {x_("edif"), io_ednoop, KEDIF, Sedif},
680 {x_("edifLevel"), io_ednoop, KEDIFLEVEL, SedifLevel},
681 {x_("edifVersion"), io_ednoop, KEDIFVERSION, SedifVersion},
682 {x_("endType"), io_edendType, KENDTYPE, KNULL},
683 {x_("external"), io_edlibrary, KEXTERNAL, Slibrary},
684 {x_("fabricate"), io_edfabricate, KFABRICATE, KNULL},
685 {x_("false"), io_edfalse, KFALSE, KNULL},
686 {x_("figure"), io_edfigure, KFIGURE, KNULL},
687 {x_("figureGroup"), io_ednoop, KFIGUREGROUP, KNULL},
688 {x_("figureGroupOverride"), io_edfigureGroupOverride, KFIGUREGROUPOVERRIDE, KNULL},
689 {x_("fillpattern"), io_ednoop, KFILLPATTERN, KNULL},
690 {x_("gridMap"), io_ednoop, KGRIDMAP, KNULL},
691 {x_("instance"), io_edinstance, KINSTANCE, Sinstance},
692 {x_("instanceRef"), io_edinstanceRef, KINSTANCEREF, SinstanceRef},
693 {x_("integer"), io_edinteger, KINTEGER, KNULL},
694 {x_("interface"), io_edinterface, KINTERFACE, Sinterface},
695 {x_("joined"), io_edjoined, KJOINED, Sjoined},
696 {x_("justify"), io_edjustify, KJUSTIFY, KNULL},
697 {x_("keywordDisplay"), io_ednoop, KKEYWORDDISPLAY, KNULL},
698 {x_("keywordLevel"), io_ednoop, KEDIFKEYLEVEL, KNULL},
699 {x_("keywordMap"), io_ednoop, KEDIFKEYMAP, SkeywordMap},
700 {x_("library"), io_edlibrary, KLIBRARY, Slibrary},
701 {x_("libraryRef"), io_ednoop, KLIBRARYREF, SlibraryRef},
702 {x_("listOfNets"), io_ednoop, KLISTOFNETS, SlistOfNets},
703 {x_("listOfPorts"), io_ednoop, KLISTOFPORTS, KNULL},
704 {x_("member"), io_edmember, KMEMBER, KNULL},
705 {x_("name"), io_edname, KNAME, KNULL},
706 {x_("net"), io_ednet, KNET, Snet},
707 {x_("netBundle"), io_ednetBundle, KNETBUNDLE, SnetBundle},
708 {x_("number"), io_ednumber, KNUMBER, KNULL},
709 {x_("numberDefinition"), io_ednoop, KNUMBERDEFINITION, SnumberDefinition},
710 {x_("openShape"), io_edopenShape, KOPENSHAPE, KNULL},
711 {x_("orientation"), io_edorientation, KORIENTATION, KNULL},
712 {x_("origin"), io_ednoop, KORIGIN, KNULL},
713 {x_("owner"), io_ednoop, KOWNER, KNULL},
714 {x_("page"), io_edpage, KPAGE, KNULL},
715 {x_("pageSize"), io_ednoop, KPAGESIZE, KNULL},
716 {x_("path"), io_edpath, KPATH, KNULL},
717 {x_("pathWidth"), io_edpathWidth, KPATHWIDTH, KNULL},
718 {x_("point"), io_edpoint, KPOINT, KNULL},
719 {x_("pointList"), io_edpointList, KPOINTLIST, KNULL},
720 {x_("polygon"), io_edpolygon, KPOLYGON, KNULL},
721 {x_("port"), io_edport, KPORT, Sport},
722 {x_("portBundle"), io_ednoop, KPORTBUNDLE, KNULL},
723 {x_("portImplementation"), io_edportImplementation, KPORTIMPLEMENTATION, KNULL},
724 {x_("portInstance"), io_ednoop,KPORTINSTANCE, KNULL},
725 {x_("portList"), io_ednoop, KPORTLIST, KNULL},
726 {x_("portRef"), io_edportRef, KPORTREF, KNULL},
727 {x_("program"), io_edprogram, KPROGRAM, KNULL},
728 {x_("property"), io_edproperty, KPROPERTY, KNULL},
729 {x_("propertyDisplay"), io_ednoop, KPROPERTYDISPLAY, KNULL},
730 {x_("pt"), io_edpt, KPT, KNULL},
731 {x_("rectangle"), io_edrectangle, KRECTANGLE, KNULL},
732 {x_("rename"), io_edrename, KRENAME, KNULL},
733 {x_("scale"), io_edscale, KSCALE, Sscale},
734 {x_("scaleX"), io_ednoop, KSCALEX, KNULL},
735 {x_("scaleY"), io_ednoop, KSCALEY, KNULL},
736 {x_("shape"), io_ednoop, KSHAPE, KNULL},
737 {x_("status"), io_ednoop, KSTATUS, Sstatus},
738 {x_("string"), io_edstring, KSTRING, KNULL},
739 {x_("stringDisplay"), io_edstringDisplay, KSTRINGDISPLAY, KNULL},
740 {x_("symbol"), io_edsymbol, KSYMBOL, Ssymbol},
741 {x_("technology"), io_edtechnology, KTECHNOLOGY, Stechnology},
742 {x_("textHeight"), io_edtextHeight, KTEXTHEIGHT, KNULL},
743 {x_("timestamp"), io_ednoop, KTIMESTAMP, Stimestamp},
744 {x_("transform"), io_ednoop, KTRANSFORM, KNULL},
745 {x_("true"), io_edtrue, KTRUE, KNULL},
746 {x_("unit"), io_edunit, KUNIT, Sunit},
747 {x_("userData"), io_ednoop, KUSERDATA, KNULL},
748 {x_("version"), io_ednoop, KVERSION, KNULL},
749 {x_("view"), io_edview, KVIEW, Sview},
750 {x_("viewRef"), io_ednoop, KVIEWREF, SviewRef},
751 {x_("viewType"), io_edviewType, KVIEWTYPE, SviewType},
752 {x_("visible"), io_ednoop, KVISIBLE, KNULL},
753 {x_("written"), io_ednoop, KWRITTEN, Swritten},
754 {0,0,KUNKNOWN,0}
755 };
756
757 /* edif keyword stack, this stack matches the current depth of the EDIF file,
758 for the keyword instance it would be KEDIF, KLIBRARY, KCELL, KCONTENTS, KINSTANCE
759 */
760 static KSTATE kstack[1000];
761 static INTBIG kstack_ptr = 0;
762 static INTBIG filelen, filepos;
763
764 /* some standard artwork primitivies */
765 static PORTPROTO *default_port = NOPORTPROTO;
766 static PORTPROTO *default_iconport = NOPORTPROTO;
767 static PORTPROTO *default_busport = NOPORTPROTO;
768 static PORTPROTO *default_input = NOPORTPROTO;
769 static PORTPROTO *default_output = NOPORTPROTO;
770 INTBIG EDIF_name_key = 0;
771 static INTBIG EDIF_array_key = 0;
772 static INTBIG EDIF_annotate_key = 0;
773 static void *io_edifprogressdialog;
774 static struct
775 {
776 int width;
777 int height;
778 } EDIF_sheet_bounds[MAXSHEETS] =
779 {
780 {8, 10},
781 {16, 10},
782 {16, 20},
783 {32, 20},
784 {32, 40},
785 {64, 40}
786 };
787
788 #define RET_NOMEMORY() { ttyputnomemory(); return(1); }
789
790
791 /*
792 * Routine to free all memory associated with this module.
793 */
io_freeedifinmemory(void)794 void io_freeedifinmemory(void)
795 {
796 EDNETPORT_PTR nport, nnport;
797
798 /* free the netport freelist */
799 for (nport = io_edifgbl.free_netports; nport != NOEDNETPORT; nport = nnport)
800 {
801 nnport = nport->next;
802 efree((CHAR *)nport);
803 }
804 if (io_edifgbl.ptype == PSTRING) efree(io_edifgbl.pval.string);
805 io_edfreesavedptlist();
806 io_edfreeptlist();
807 }
808
809 /*
810 * routine to write a ".edif" file from the library "lib"
811 */
io_readediflibrary(LIBRARY * lib)812 BOOLEAN io_readediflibrary(LIBRARY *lib)
813 {
814 INTBIG key_count, i;
815 CHAR *filename, *msg;
816 NODEPROTO *np;
817 REGISTER VARIABLE *var;
818 REGISTER void *infstr;
819
820 io_edifgbl.edif_file = xopen(lib->libfile, io_filetypeedif, x_(""), &filename);
821 if (io_edifgbl.edif_file == NULL)
822 {
823 ttyputerr(_("File %s not found"), lib->libfile);
824 return(TRUE);
825 }
826 filelen = filesize(io_edifgbl.edif_file);
827 filepos = 0;
828
829 /* one-time inits */
830 if (!io_edgblinited)
831 {
832 io_edifgbl.firstnetport = io_edifgbl.lastnetport = io_edifgbl.free_netports = NOEDNETPORT;
833 io_edifgbl.ptype = PUNKNOWN;
834 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
835 io_edifgbl.pt_count = 0;
836 io_edifgbl.save_text.points = NOEPT;
837 io_edifgbl.save_text.pt_count = 0;
838 io_edgblinited = TRUE;
839 }
840
841 /* parser inits */
842 io_edifgbl.state = KINIT;
843 io_edifgbl.lineno = 1;
844 io_edifgbl.buffer[0] = 0;
845 io_edifgbl.pos = io_edifgbl.buffer;
846 io_edifgbl.delimeters = DELIMETERS;
847 io_edifgbl.errors = io_edifgbl.warnings = 0;
848 io_edifgbl.ignoreblock = 0;
849 io_edifgbl.vendor = EVUNKNOWN;
850
851 /* general inits */
852 var = getval((INTBIG)io_tool, VTOOL, VFLOAT, x_("IO_edif_input_scale"));
853 if (var == NOVARIABLE) io_edifgbl.scale = 1.0; else
854 io_edifgbl.scale = castfloat(var->addr);
855 io_edifgbl.dbunit = 1.0;
856 /* io_edifgbl.meters = 0.000000001; */ /* default 1 db unit per nanometer */
857 io_edifgbl.meters = scaletodispunit(1, DISPUNITCM) / 100.0;
858 io_edifgbl.library = lib;
859 io_edifgbl.technology = sch_tech;
860 io_edifgbl.celltbl_sze = io_edifgbl.celltbl_cnt = 0;
861 io_edifgbl.ports = io_edifgbl.free_ports = NOEDPORT;
862 io_edifgbl.properties = io_edifgbl.free_properties = NOEDPROPERTY;
863 io_edfreenetports();
864
865 /* active database inits */
866 io_edifgbl.current_cell = NONODEPROTO;
867 io_edifgbl.current_node = NONODEINST;
868 io_edifgbl.current_arc = NOARCINST;
869 io_edifgbl.current_port = NOPORTPROTO;
870 io_edifgbl.figure_group = NONODEPROTO;
871 io_edifgbl.arc_type = NOARCPROTO;
872 io_edifgbl.proto = NONODEPROTO;
873
874 /* name inits */
875 io_edifgbl.cell_reference[0] = 0;
876 io_edifgbl.port_reference[0] = 0;
877 io_edifgbl.instance_reference[0] = 0;
878 io_edifgbl.bundle_reference[0] = 0;
879 io_edifgbl.net_reference[0] = 0;
880 io_edifgbl.property_reference[0] = 0;
881
882 /* geometry inits */
883 io_edifgbl.layer_ptr = 0;
884 io_edifgbl.cur_nametbl = NONAMETABLE;
885 io_edfreeptlist();
886
887 /* text inits */
888 io_edifgbl.textheight = 0;
889 io_edifgbl.justification = LOWERLEFT;
890 io_edifgbl.visible = 1;
891 io_edifgbl.save_text.string[0] = 0;
892 io_edfreesavedptlist();
893
894 io_edifgbl.sheet_size = SHEET_DSIZE;
895 io_edifgbl.sh_xpos = -1;
896 io_edifgbl.sh_ypos = -1;
897
898 kstack_ptr = 0;
899
900 if (default_port == NOPORTPROTO) default_port = getportproto(sch_wirepinprim, x_("wire"));
901 default_iconport = sch_wirepinprim->firstportproto;
902 if (default_busport == NOPORTPROTO) default_busport = getportproto(sch_buspinprim, x_("bus"));
903 if (default_input == NOPORTPROTO) default_input = getportproto(sch_offpageprim, x_("y"));
904 if (default_output == NOPORTPROTO) default_output = getportproto(sch_offpageprim, x_("a"));
905
906 if (EDIF_name_key == 0) EDIF_name_key = makekey(x_("EDIF_name"));
907 if (EDIF_array_key == 0) EDIF_array_key = makekey(x_("EDIF_array"));
908 if (EDIF_annotate_key == 0) EDIF_annotate_key = makekey(x_("EDIF_annotate"));
909
910 /* now load the edif netlist */
911 infstr = initinfstr();
912 formatinfstr(infstr, _("Reading %s"), filename);
913 msg = returninfstr(infstr);
914 if (io_verbose < 0)
915 {
916 io_edifprogressdialog = DiaInitProgress(msg, 0);
917 if (io_edifprogressdialog == 0)
918 {
919 xclose(io_edifgbl.edif_file);
920 return(TRUE);
921 }
922 DiaSetProgress(io_edifprogressdialog, 0, filelen);
923 } else ttyputmsg(msg);
924
925 /* count the number of keywords */
926 key_count = 0;
927 while (edif_keywords[key_count].name != 0) key_count++;
928 if (io_edload_edif(key_count, edif_keywords))
929 {
930 ttyputerr(_("error: bad design, aborting netlist translation"));
931 if (io_verbose < 0) DiaDoneProgress(io_edifprogressdialog);
932 return(TRUE);
933 }
934 if (io_edifgbl.errors || io_edifgbl.warnings)
935 ttyputmsg(_("info: a total of %d errors, and %d warnings encountered during load"),
936 io_edifgbl.errors, io_edifgbl.warnings);
937
938 xclose(io_edifgbl.edif_file);
939 if (io_verbose < 0)
940 {
941 DiaSetProgress(io_edifprogressdialog, 999, 1000);
942 DiaSetTextProgress(io_edifprogressdialog, _("Cleaning Up..."));
943 }
944
945 /* free the layer table */
946 for (i = 0; i < io_edifgbl.layer_ptr; i++)
947 {
948 if (io_edifgbl.nametbl[i]->original != io_edifgbl.nametbl[i]->replace)
949 efree(io_edifgbl.nametbl[i]->replace);
950 efree(io_edifgbl.nametbl[i]->original);
951 efree((CHAR *)io_edifgbl.nametbl[i]);
952 }
953 /* note the master list is static */
954
955 /* now the cell name table */
956 for(i = 0; i < io_edifgbl.celltbl_cnt; i++)
957 {
958 if (io_edifgbl.celltbl[i]->original != io_edifgbl.celltbl[i]->replace)
959 efree(io_edifgbl.celltbl[i]->replace);
960 efree(io_edifgbl.celltbl[i]->original);
961 efree((CHAR *)io_edifgbl.celltbl[i]);
962 }
963
964 /* and the master list ... */
965 if (io_edifgbl.celltbl_cnt != 0)
966 {
967 efree((CHAR *)io_edifgbl.celltbl);
968 } else
969 {
970 ttyputerr(_("error: no data"));
971 if (io_verbose < 0) DiaDoneProgress(io_edifprogressdialog);
972 return(TRUE);
973 }
974
975 if (io_edifgbl.library->curnodeproto == NONODEPROTO)
976 io_edifgbl.library->curnodeproto = io_edifgbl.library->firstnodeproto;
977
978 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
979 net_examinenodeproto(np);
980
981 /* recompute bounds */
982 (*el_curconstraint->solve)(NONODEPROTO);
983
984 if (io_verbose < 0) DiaDoneProgress(io_edifprogressdialog);
985 return(FALSE);
986 }
987
988 /*
989 * Module: io_edload_edif
990 * Function: Will load the edif netlist into memory
991 * Method: Does a simple keyword lookup to load the lisp structured
992 * EDIF language into Electric's database
993 */
io_edload_edif(INTBIG key_count,EDIFKEY_PTR keywords)994 INTBIG io_edload_edif(INTBIG key_count, EDIFKEY_PTR keywords)
995 {
996 KSTATE *state;
997 CHAR *msg;
998 CHAR *token, word[WORD+1];
999 INTBIG low, high, mid, change, errcode;
1000 INTBIG keycount;
1001 INTBIG savestack;
1002
1003 /* setup the error return location */
1004 errcode = setjmp(io_edifgbl.env);
1005 if (errcode != 0)
1006 {
1007 switch (errcode)
1008 {
1009 case LONGJMPEOF: msg = _("Unexpected end-of-file"); break;
1010 case LONGJMPNOMEM: msg = _("No memory"); break;
1011 case LONGJMPPTMIS: msg = _("Point list mismatch"); break;
1012 case LONGJMPNOLIB: msg = _("Could not create library"); break;
1013 case LONGJMPNOINT: msg = _("No integer value"); break;
1014 case LONGJMPILLNUM: msg = _("Illegal number value"); break;
1015 case LONGJMPNOMANT: msg = _("No matissa value"); break;
1016 case LONGJMPNOEXP: msg = _("No exponent value"); break;
1017 case LONGJMPILLNAME: msg = _("Illegal name"); break;
1018 case LONGJMPILLDELIM: msg = _("Illegal delimeter"); break;
1019 default: msg = _("Unknown error"); break;
1020 }
1021 ttyputerr(_("line #%d: %s"), io_edifgbl.lineno, msg);
1022 return(1);
1023 }
1024
1025 savestack = -1;
1026
1027 /* now read and parse the edif netlist */
1028 keycount = 0;
1029 while ((token = io_edget_keyword(word)) != NULL)
1030 {
1031 keycount++;
1032 if ((keycount%100) == 0)
1033 {
1034 if (io_verbose < 0) DiaSetProgress(io_edifprogressdialog, filepos, filelen); else
1035 ttyputmsg(_("%ld keywords read (%d%% done)"), keycount, filepos*100/filelen);
1036 }
1037
1038 /* locate the keyword, and execute the function */
1039 low = 0;
1040 high = key_count - 1;
1041 while (low <= high)
1042 {
1043 mid = (low + high) / 2;
1044 change = namesame(token, keywords[mid].name);
1045 if (change < 0) high = mid - 1; else
1046 if (change > 0) low = mid + 1; else
1047 {
1048 /* found the function, check state */
1049 if (keywords[mid].state != KNULL && io_edifgbl.state != KUNKNOWN)
1050 {
1051 state = keywords[mid].state;
1052 while (*state && io_edifgbl.state != *state) state++;
1053 if (io_edifgbl.state != *state)
1054 {
1055 ttyputerr(_("error, line #%d: illegal state for keyword <%s>"),
1056 io_edifgbl.lineno, token);
1057 io_edifgbl.errors++;
1058 }
1059 }
1060
1061 /* call the function */
1062 kstack[kstack_ptr++] = io_edifgbl.state;
1063 io_edifgbl.state = keywords[mid].next;
1064 if (savestack >= kstack_ptr)
1065 {
1066 savestack = -1;
1067 io_edifgbl.ignoreblock = 0;
1068 }
1069 if (!io_edifgbl.ignoreblock) (keywords[mid].func)();
1070 if (io_edifgbl.ignoreblock)
1071 {
1072 if (savestack == -1) savestack = kstack_ptr;
1073 }
1074 break;
1075 }
1076 }
1077 if (low > high)
1078 {
1079 ttyputerr(_("warning, line #%d: unknown keyword <%s>"), io_edifgbl.lineno, token);
1080 io_edifgbl.warnings++;
1081 kstack[kstack_ptr++] = io_edifgbl.state;
1082 io_edifgbl.state = KUNKNOWN;
1083 }
1084 }
1085 if (io_edifgbl.state != KINIT)
1086 {
1087 ttyputerr(_("line #%d: unexpected end-of-file encountered"), io_edifgbl.lineno);
1088 io_edifgbl.errors++;
1089 }
1090 return(0);
1091 }
1092
1093 /* parser routines */
io_ednoop(void)1094 INTBIG io_ednoop(void)
1095 {
1096 return(0);
1097 }
1098
io_edtechnology(void)1099 INTBIG io_edtechnology(void)
1100 {
1101 return(0);
1102 }
1103
io_edfabricate(void)1104 INTBIG io_edfabricate(void)
1105 {
1106 INTBIG pos;
1107 CHAR name[WORD+1];
1108
1109 pos = io_edifgbl.layer_ptr;
1110
1111 io_edifgbl.nametbl[pos] = (NAMETABLE_PTR)emalloc(sizeof(NAMETABLE), io_tool->cluster);
1112 if (io_edifgbl.nametbl[pos] == NONAMETABLE) RET_NOMEMORY();
1113
1114 /* first get the original and replacement layers */
1115 if ((io_edget_token(name, 0)) == NULL)
1116 longjmp(io_edifgbl.env, LONGJMPEOF);
1117 if (allocstring(&io_edifgbl.nametbl[pos]->original, name, io_tool->cluster)) RET_NOMEMORY();
1118 if ((io_edget_token(name, 0)) == NULL)
1119 longjmp(io_edifgbl.env, LONGJMPEOF);
1120 if (allocstring(&io_edifgbl.nametbl[pos]->replace, name, io_tool->cluster)) RET_NOMEMORY();
1121 io_edifgbl.nametbl[pos]->textheight = 0;
1122 io_edifgbl.nametbl[pos]->justification = LOWERLEFT;
1123 io_edifgbl.nametbl[pos]->visible = 1;
1124
1125 /* now bump the position */
1126 io_edifgbl.layer_ptr++;
1127 return(0);
1128 }
1129
io_edpage(void)1130 INTBIG io_edpage(void)
1131 {
1132 CHAR view[WORD+1], cname[WORD+1];
1133 NODEPROTO *proto;
1134
1135 /* check for the name */
1136 (void)io_edcheck_name();
1137
1138 (void)esnprintf(view, WORD+1, x_("p%d"), ++io_edifgbl.pageno);
1139
1140 /* locate this in the list of cells */
1141 for (proto = io_edifgbl.library->firstnodeproto; proto != NONODEPROTO; proto = proto->nextnodeproto)
1142 {
1143 if (!namesame(proto->protoname, io_edifgbl.cell_name) &&
1144 !namesame(proto->cellview->sviewname, view)) break;
1145 }
1146 if (proto == NONODEPROTO)
1147 {
1148 /* allocate the cell */
1149 esnprintf(cname, WORD+1, x_("%s{%s}"), io_edifgbl.cell_name, view);
1150 proto = us_newnodeproto(cname, io_edifgbl.library);
1151 if (proto == NONODEPROTO) longjmp(io_edifgbl.env, LONGJMPNOMEM);
1152 proto->temp1 = 0;
1153 }
1154 else if (proto->temp1) io_edifgbl.ignoreblock = 1;
1155
1156 io_edifgbl.current_cell = proto;
1157 return(0);
1158 }
1159
io_edfigure(void)1160 INTBIG io_edfigure(void)
1161 {
1162 CHAR layer[WORD+1];
1163 INTBIG low, high, change, mid;
1164 INTBIG pos;
1165
1166 /* get the layer name */
1167 /* check for figuregroup override */
1168 if (*io_edpos_token() == '(') return(0);
1169 if (io_edget_token(layer, 0) == NULL)
1170 longjmp(io_edifgbl.env, LONGJMPEOF);
1171
1172 /* now look for this layer in the list of layers */
1173 low = 0;
1174 high = io_edifgbl.layer_ptr - 1;
1175 while (low <= high)
1176 {
1177 mid = (low + high) / 2;
1178 change = namesame(layer, io_edifgbl.nametbl[mid]->original);
1179 if (change < 0) high = mid - 1; else
1180 if (change > 0) low = mid + 1; else
1181 {
1182 /* found the layer */
1183 io_edifgbl.figure_group = io_edifgbl.nametbl[mid]->node;
1184 io_edifgbl.arc_type = io_edifgbl.nametbl[mid]->arc;
1185 io_edifgbl.textheight = io_edifgbl.nametbl[mid]->textheight;
1186 io_edifgbl.justification = io_edifgbl.nametbl[mid]->justification;
1187 io_edifgbl.visible = io_edifgbl.nametbl[mid]->visible;
1188
1189 /* allow new definitions */
1190 io_edifgbl.cur_nametbl = io_edifgbl.nametbl[mid];
1191 break;
1192 }
1193 }
1194 if (low > high)
1195 {
1196 pos = io_edifgbl.layer_ptr;
1197 io_edifgbl.nametbl[pos] = (NAMETABLE_PTR)emalloc(sizeof(NAMETABLE), io_tool->cluster);
1198 if (io_edifgbl.nametbl[pos] == NONAMETABLE ||
1199 allocstring(&io_edifgbl.nametbl[pos]->original, layer, io_tool->cluster))
1200 longjmp(io_edifgbl.env, LONGJMPNOMEM);
1201 io_edifgbl.nametbl[pos]->replace = io_edifgbl.nametbl[pos]->original;
1202 io_edifgbl.figure_group = io_edifgbl.nametbl[pos]->node = art_boxprim;
1203 io_edifgbl.arc_type = io_edifgbl.nametbl[pos]->arc = sch_wirearc;
1204 io_edifgbl.textheight = io_edifgbl.nametbl[pos]->textheight = 0;
1205 io_edifgbl.justification = io_edifgbl.nametbl[pos]->justification = LOWERLEFT;
1206 io_edifgbl.visible = io_edifgbl.nametbl[pos]->visible = 1;
1207
1208 /* allow new definitions */
1209 io_edifgbl.cur_nametbl = io_edifgbl.nametbl[pos];
1210
1211 /* now sort the list */
1212 io_edifgbl.layer_ptr++;
1213 esort(io_edifgbl.nametbl, io_edifgbl.layer_ptr, sizeof(NAMETABLE_PTR),
1214 io_edcompare_name);
1215 }
1216 return(0);
1217 }
1218
io_edfigureGroupOverride(void)1219 INTBIG io_edfigureGroupOverride(void)
1220 {
1221 return(io_edgetlayer());
1222 }
1223
io_edscale(void)1224 INTBIG io_edscale(void)
1225 {
1226 /* get the scale */
1227 io_edifgbl.val1 = io_edgetnumber();
1228 io_edifgbl.val2 = io_edgetnumber();
1229 return(0);
1230 }
1231
io_edendType(void)1232 INTBIG io_edendType(void)
1233 {
1234 CHAR type[WORD+1];
1235
1236 /* get the endtype */
1237 if (io_edget_token(type, 0) == NULL)
1238 longjmp(io_edifgbl.env, LONGJMPEOF);
1239
1240 if (!namesame(type, x_("EXTEND"))) io_edifgbl.extend_end = 1;
1241 return(0);
1242 }
1243
io_edcornerType(void)1244 INTBIG io_edcornerType(void)
1245 {
1246 CHAR type[WORD+1];
1247
1248 /* get the endtype */
1249 if (io_edget_token(type, 0) == NULL)
1250 longjmp(io_edifgbl.env, LONGJMPEOF);
1251
1252 if (!namesame(type, x_("EXTEND"))) io_edifgbl.extend_corner = 1;
1253 return(0);
1254 }
1255
io_edstringDisplay(void)1256 INTBIG io_edstringDisplay(void)
1257 {
1258 INTBIG kptr;
1259
1260 /* init the point lists */
1261 io_edfreeptlist();
1262 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1263 io_edifgbl.orientation = OR0;
1264 io_edifgbl.visible = 1;
1265 io_edifgbl.justification = LOWERLEFT;
1266 io_edifgbl.textheight = 0;
1267
1268 /* get the string, remove the quote */
1269 io_edget_delim('\"');
1270 if (io_edget_token(io_edifgbl.string, '\"') == NULL)
1271 longjmp(io_edifgbl.env, LONGJMPEOF);
1272
1273 /* check for RENAME */
1274 if (kstack[kstack_ptr-1] != KRENAME) return(0);
1275 (void)estrcpy(io_edifgbl.original, io_edifgbl.string);
1276 if (kstack[kstack_ptr - 2] == KARRAY) kptr = kstack_ptr - 3; else
1277 kptr = kstack_ptr - 2;
1278 switch (kstack[kptr])
1279 {
1280 case KCELL:
1281 (void)estrcpy(io_edifgbl.cell_name, io_edifgbl.original);
1282 break;
1283 case KPORT:
1284 (void)estrcpy(io_edifgbl.port_name, io_edifgbl.original);
1285 break;
1286 case KINSTANCE:
1287 (void)estrcpy(io_edifgbl.instance_name, io_edifgbl.original);
1288 break;
1289 case KNET:
1290 (void)estrcpy(io_edifgbl.net_name, io_edifgbl.original);
1291 break;
1292 case KNETBUNDLE:
1293 (void)estrcpy(io_edifgbl.bundle_name, io_edifgbl.original);
1294 break;
1295 case KPROPERTY:
1296 (void)estrcpy(io_edifgbl.property_name, io_edifgbl.original);
1297 break;
1298 default:
1299 break;
1300 }
1301 return(0);
1302 }
1303
io_edtrue(void)1304 INTBIG io_edtrue(void)
1305 {
1306 /* check previous keyword */
1307 if (kstack_ptr > 1 && kstack[kstack_ptr-1] == KVISIBLE)
1308 {
1309 io_edifgbl.visible = 1;
1310 if (io_edifgbl.cur_nametbl != NONAMETABLE)
1311 io_edifgbl.cur_nametbl->visible = 1;
1312 }
1313 return(0);
1314 }
1315
io_edfalse(void)1316 INTBIG io_edfalse(void)
1317 {
1318 /* check previous keyword */
1319 if (kstack_ptr > 1 && kstack[kstack_ptr-1] == KVISIBLE)
1320 {
1321 io_edifgbl.visible = 0;
1322 if (io_edifgbl.cur_nametbl != NONAMETABLE)
1323 io_edifgbl.cur_nametbl->visible = 0;
1324 }
1325 return(0);
1326 }
1327
io_edgetlayer(void)1328 INTBIG io_edgetlayer(void)
1329 {
1330 CHAR layer[WORD+1];
1331 INTBIG low, high, change, mid;
1332 INTBIG pos;
1333
1334 /* get the layer name */
1335 if (io_edget_token(layer, 0) == NULL)
1336 longjmp(io_edifgbl.env, LONGJMPEOF);
1337
1338 /* now look for this layer in the list of layers */
1339 low = 0;
1340 high = io_edifgbl.layer_ptr - 1;
1341 while (low <= high)
1342 {
1343 mid = (low + high) / 2;
1344 change = namesame(layer, io_edifgbl.nametbl[mid]->original);
1345 if (change < 0) high = mid - 1; else
1346 if (change > 0) low = mid + 1; else
1347 {
1348 /* found the layer */
1349 io_edifgbl.figure_group = io_edifgbl.nametbl[mid]->node;
1350 io_edifgbl.arc_type = io_edifgbl.nametbl[mid]->arc;
1351 io_edifgbl.textheight = io_edifgbl.nametbl[mid]->textheight;
1352 io_edifgbl.justification = io_edifgbl.nametbl[mid]->justification;
1353 io_edifgbl.visible = io_edifgbl.nametbl[mid]->visible;
1354 break;
1355 }
1356 }
1357 if (low > high)
1358 {
1359 #ifdef LAYERWARNING
1360 ttyputerr(_("warning, line #%d: unknown layer <%s>"), io_edifgbl.lineno, layer);
1361 io_edifgbl.warnings++;
1362 #endif
1363
1364 /* insert and resort the list */
1365 pos = io_edifgbl.layer_ptr;
1366
1367 io_edifgbl.nametbl[pos] = (NAMETABLE_PTR)emalloc(sizeof(NAMETABLE), io_tool->cluster);
1368 if (io_edifgbl.nametbl[pos] == NONAMETABLE ||
1369 allocstring(&io_edifgbl.nametbl[pos]->original, layer, io_tool->cluster))
1370 longjmp(io_edifgbl.env, LONGJMPNOMEM);
1371
1372 io_edifgbl.nametbl[pos]->replace = io_edifgbl.nametbl[pos]->original;
1373 io_edifgbl.figure_group = io_edifgbl.nametbl[pos]->node = art_boxprim;
1374 io_edifgbl.arc_type = io_edifgbl.nametbl[pos]->arc = sch_wirearc;
1375 io_edifgbl.textheight = io_edifgbl.nametbl[pos]->textheight = 0;
1376 io_edifgbl.justification = io_edifgbl.nametbl[pos]->justification = LOWERLEFT;
1377 io_edifgbl.visible = io_edifgbl.nametbl[pos]->visible = 1;
1378
1379 /* now sort the list */
1380 io_edifgbl.layer_ptr++;
1381 esort(io_edifgbl.nametbl, io_edifgbl.layer_ptr, sizeof(NAMETABLE_PTR),
1382 io_edcompare_name);
1383 }
1384 return(0);
1385 }
1386
1387 /* geometry routines */
io_edpointList(void)1388 INTBIG io_edpointList(void)
1389 {
1390 return(0);
1391 }
1392
io_edpoint(void)1393 INTBIG io_edpoint(void)
1394 {
1395 return(0);
1396 }
1397
io_edjustify(void)1398 INTBIG io_edjustify(void)
1399 {
1400 CHAR val[WORD+1];
1401
1402 /* get the textheight value of the point */
1403 if (io_edget_token(val, 0) == NULL)
1404 longjmp(io_edifgbl.env, LONGJMPEOF);
1405 if (namesame(val, x_("UPPERLEFT")))
1406 io_edifgbl.justification = UPPERLEFT;
1407 else if (namesame(val, x_("UPPERCENTER")))
1408 io_edifgbl.justification = UPPERCENTER;
1409 else if (namesame(val, x_("UPPERRIGHT")))
1410 io_edifgbl.justification = UPPERRIGHT;
1411 else if (namesame(val, x_("CENTERLEFT")))
1412 io_edifgbl.justification = CENTERLEFT;
1413 else if (namesame(val, x_("CENTERCENTER")))
1414 io_edifgbl.justification = CENTERCENTER;
1415 else if (namesame(val, x_("CENTERRIGHT")))
1416 io_edifgbl.justification = CENTERRIGHT;
1417 else if (namesame(val, x_("LOWERLEFT")))
1418 io_edifgbl.justification = LOWERLEFT;
1419 else if (namesame(val, x_("LOWERCENTER")))
1420 io_edifgbl.justification = LOWERCENTER;
1421 else if (namesame(val, x_("LOWERRIGHT")))
1422 io_edifgbl.justification = LOWERRIGHT;
1423 else
1424 {
1425 ttyputerr(_("warning, line #%d: unknown keyword <%s>"), io_edifgbl.lineno, val);
1426 io_edifgbl.warnings++;
1427 return(0);
1428 }
1429
1430 if (io_edifgbl.cur_nametbl != NONAMETABLE)
1431 io_edifgbl.cur_nametbl->justification = io_edifgbl.justification;
1432 return(0);
1433 }
1434
io_edtextHeight(void)1435 INTBIG io_edtextHeight(void)
1436 {
1437 CHAR val[WORD+1];
1438
1439 /* get the textheight value of the point */
1440 if (io_edget_token(val, 0) == NULL)
1441 longjmp(io_edifgbl.env, LONGJMPEOF);
1442 io_edifgbl.textheight = (INTBIG)(eatol(val) * io_edifgbl.scale);
1443
1444 if (io_edifgbl.cur_nametbl != NONAMETABLE)
1445 io_edifgbl.cur_nametbl->textheight = io_edifgbl.textheight;
1446
1447 return(0);
1448 }
1449
io_edpt(void)1450 INTBIG io_edpt(void)
1451 {
1452 CHAR xstr[WORD+1], ystr[WORD+1];
1453 EPT_PTR point;
1454 INTBIG x, y, s;
1455
1456 /* get the x and y values of the point */
1457 if (io_edget_token(xstr, 0) == NULL)
1458 longjmp(io_edifgbl.env, LONGJMPEOF);
1459 if (io_edget_token(ystr, 0) == NULL)
1460 longjmp(io_edifgbl.env, LONGJMPEOF);
1461
1462 if (kstack_ptr > 1 && kstack[kstack_ptr-1] == KDELTA)
1463 {
1464 x = (INTBIG)(eatol(xstr) * io_edifgbl.scale);
1465 y = (INTBIG)(eatol(ystr) * io_edifgbl.scale);
1466
1467 /* transform the points per orientation */
1468 switch (io_edifgbl.orientation)
1469 {
1470 case OR0: break;
1471 case OR90: s = x; x = -y; y = s; break;
1472 case OR180: x = -x; y = -y; break;
1473 case OR270: s = x; x = y; y = -s; break;
1474 case OMY: x = -x; break;
1475 case OMX: y = -y; break;
1476 case OMYR90: s = y; y = -x; x = -s; break;
1477 case OMXR90: s = x; x = y; y = s; break;
1478 default: break;
1479 }
1480
1481 /* set the array deltas */
1482 if (io_edifgbl.deltapts == 0)
1483 {
1484 io_edifgbl.deltaxX = x;
1485 io_edifgbl.deltaxY = y;
1486 } else
1487 {
1488 io_edifgbl.deltayX = x;
1489 io_edifgbl.deltayY = y;
1490 }
1491 io_edifgbl.deltapts++;
1492 } else
1493 {
1494 /* allocate a point to read */
1495 point = (EPT_PTR) emalloc(sizeof (EPT), io_tool->cluster);
1496 if (point == NOEPT) RET_NOMEMORY();
1497
1498 /* and set the values */
1499 point->x = eatol(xstr);
1500 if (point->x > 0) point->x = (INTBIG)(point->x * io_edifgbl.scale + 0.5); else
1501 point->x = (INTBIG)(point->x * io_edifgbl.scale - 0.5);
1502 point->y = eatol(ystr);
1503 if (point->y > 0) point->y = (INTBIG)(point->y * io_edifgbl.scale + 0.5); else
1504 point->y = (INTBIG)(point->y * io_edifgbl.scale - 0.5);
1505 point->nextpt = NOEPT;
1506
1507 /* add it to the list of points */
1508 if (io_edifgbl.points) io_edifgbl.lastpt->nextpt = point; else
1509 io_edifgbl.points = point;
1510 io_edifgbl.lastpt = point;
1511 io_edifgbl.pt_count++;
1512 }
1513 return(0);
1514 }
1515
io_edorientation(void)1516 INTBIG io_edorientation(void)
1517 {
1518 CHAR orient[WORD+1];
1519
1520 /* get the orientation keyword */
1521 if (io_edget_token(orient, 0) == NULL)
1522 longjmp(io_edifgbl.env, LONGJMPEOF);
1523
1524 if (!namesame(orient, x_("R0"))) io_edifgbl.orientation = OR0;
1525 else if (!namesame(orient, x_("R90"))) io_edifgbl.orientation = OR90;
1526 else if (!namesame(orient, x_("R180"))) io_edifgbl.orientation = OR180;
1527 else if (!namesame(orient, x_("R270"))) io_edifgbl.orientation = OR270;
1528 else if (!namesame(orient, x_("MY"))) io_edifgbl.orientation = OMY;
1529 else if (!namesame(orient, x_("MX"))) io_edifgbl.orientation = OMX;
1530 else if (!namesame(orient, x_("MYR90"))) io_edifgbl.orientation = OMYR90;
1531 else if (!namesame(orient, x_("MXR90"))) io_edifgbl.orientation = OMXR90;
1532 else
1533 {
1534 ttyputerr(_("warning, line #%d: unknown orientation value <%s>"), io_edifgbl.lineno, orient);
1535 io_edifgbl.warnings++;
1536 }
1537 return(0);
1538 }
1539
io_edpathWidth(void)1540 INTBIG io_edpathWidth(void)
1541 {
1542 CHAR width[WORD+1];
1543
1544 /* get the width string */
1545 if (io_edget_token(width, 0) == NULL)
1546 longjmp(io_edifgbl.env, LONGJMPEOF);
1547
1548 io_edifgbl.path_width = eatol(width);
1549
1550 return(0);
1551 }
1552
io_edrectangle(void)1553 INTBIG io_edrectangle(void)
1554 {
1555 io_edfreeptlist();
1556 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1557 io_edifgbl.orientation = OR0;
1558 return(0);
1559 }
1560
io_edcircle(void)1561 INTBIG io_edcircle(void)
1562 {
1563 io_edfreeptlist();
1564 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1565 io_edifgbl.orientation = OR0;
1566 return(0);
1567 }
1568
io_edpath(void)1569 INTBIG io_edpath(void)
1570 {
1571 io_edfreeptlist();
1572 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1573 io_edifgbl.orientation = OR0;
1574 io_edifgbl.path_width = 0;
1575 return(0);
1576 }
1577
io_edpolygon(void)1578 INTBIG io_edpolygon(void)
1579 {
1580 io_edfreeptlist();
1581 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1582 io_edifgbl.orientation = OR0;
1583 return(0);
1584 }
1585
io_edopenShape(void)1586 INTBIG io_edopenShape(void)
1587 {
1588 io_edfreeptlist();
1589 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1590 io_edifgbl.orientation = OR0;
1591 return(0);
1592 }
1593
io_edfreeptlist(void)1594 INTBIG io_edfreeptlist(void)
1595 {
1596 while (io_edifgbl.points != NOEPT)
1597 {
1598 io_edifgbl.lastpt = io_edifgbl.points->nextpt;
1599 efree((CHAR *)io_edifgbl.points);
1600 io_edifgbl.points = io_edifgbl.lastpt;
1601 io_edifgbl.pt_count--;
1602 }
1603 if (io_edifgbl.pt_count != 0)
1604 longjmp(io_edifgbl.env, LONGJMPPTMIS);
1605 return(0);
1606 }
1607
io_edfreesavedptlist(void)1608 INTBIG io_edfreesavedptlist(void)
1609 {
1610 EPT_PTR lastpt;
1611
1612 while (io_edifgbl.save_text.points != NOEPT)
1613 {
1614 lastpt = io_edifgbl.save_text.points->nextpt;
1615 efree((CHAR *)io_edifgbl.save_text.points);
1616 io_edifgbl.save_text.points = lastpt;
1617 io_edifgbl.save_text.pt_count--;
1618 }
1619 if (io_edifgbl.save_text.pt_count != 0)
1620 longjmp(io_edifgbl.env, LONGJMPPTMIS);
1621 return(0);
1622 }
1623
io_edprogram(void)1624 INTBIG io_edprogram(void)
1625 {
1626 CHAR program[WORD+1];
1627
1628 if (io_edget_token(program, 0) == NULL)
1629 longjmp(io_edifgbl.env, LONGJMPEOF);
1630 if (!namesamen(&program[1], x_("VIEWlogic"), 9))
1631 {
1632 io_edifgbl.vendor = EVVIEWLOGIC;
1633 } else if (!namesamen(&program[1], x_("edifout"), 7))
1634 {
1635 io_edifgbl.vendor = EVCADENCE;
1636 }
1637 return(0);
1638 }
1639
io_edunit(void)1640 INTBIG io_edunit(void)
1641 {
1642 CHAR type[WORD+1];
1643 REGISTER VARIABLE *var;
1644 float edifscale;
1645
1646 if (io_edget_token(type, 0) == NULL)
1647 longjmp(io_edifgbl.env, LONGJMPEOF);
1648 if (kstack[kstack_ptr-1] == KSCALE && !namesame(type, x_("DISTANCE")))
1649 {
1650 /* get the scale */
1651 io_edifgbl.dbunit = io_edifgbl.val1;
1652 io_edifgbl.meters = io_edifgbl.val2;
1653
1654 /* just make the scale be so that the specified number of database units becomes 1 lambda */
1655 io_edifgbl.scale = el_curlib->lambda[sch_tech->techindex];
1656
1657 var = getval((INTBIG)io_tool, VTOOL, VFLOAT, x_("IO_edif_input_scale"));
1658 if (var == NOVARIABLE) edifscale = 1.0; else
1659 edifscale = castfloat(var->addr);
1660 io_edifgbl.scale *= edifscale;
1661 }
1662 return(0);
1663 }
1664
io_edlibrary(void)1665 INTBIG io_edlibrary(void)
1666 {
1667 CHAR *name, nbuf[WORD+1];
1668
1669 /* get the name of the library */
1670 name = nbuf;
1671 if (io_edget_token(name, 0) == NULL)
1672 longjmp(io_edifgbl.env, LONGJMPEOF);
1673 #ifdef EDIFLIBNAME
1674 /* retrieve the library */
1675 io_edifgbl.library = getlibrary(name);
1676 if (io_edifgbl.library == NOLIBRARY)
1677 {
1678 /* create the library */
1679 io_edifgbl.library = newlibrary(name, name);
1680 if (io_edifgbl.library == NOLIBRARY)
1681 longjmp(io_edifgbl.env, LONGJMPNOLIB);
1682 ttyputmsg(_("Reading library %s", name);
1683 } else
1684 {
1685 /* flag existing cells */
1686 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1687 np->temp1 = 1;
1688 ttyputmsg(_("Updating library %s", name);
1689 }
1690 #endif
1691 return(0);
1692 }
1693
1694 /* cell definition routines */
1695 INTBIG io_eddesign(void)
1696 {
1697 CHAR name[WORD+1];
1698
1699 /* get the name of the cell */
1700 if (io_edget_token(name, 0) == NULL)
1701 longjmp(io_edifgbl.env, LONGJMPEOF);
1702
1703 return(0);
1704 }
1705
1706 /* note: cells are considered primitive unless they contain instance
1707 information, i.e. (contents (instance ... , this cell will become
1708 a COMPLEX cell.
1709 */
1710 INTBIG io_edcell(void)
1711 {
1712 io_edifgbl.active_view = VNULL;
1713 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
1714 io_edifgbl.pageno = 0;
1715 io_edifgbl.sh_xpos = io_edifgbl.sh_ypos = -1;
1716 if (io_edcheck_name())
1717 {
1718 (void)estrcpy(io_edifgbl.cell_reference, io_edifgbl.name);
1719 (void)estrcpy(io_edifgbl.cell_name, io_edifgbl.name);
1720 }
1721 return(0);
1722 }
1723
1724 /* view: Indicates a new view of the cell
1725 * just clears the active view flag
1726 */
1727 INTBIG io_edview(void)
1728 {
1729 io_edifgbl.active_view = VNULL;
1730 return(0);
1731 }
1732
1733 /* viewType: Indicates the view style for this cell, ie
1734 * BEHAVIOR, DOCUMENT, GRAPHIC, LOGICMODEL, MASKLAYOUT, NETLIST,
1735 * PCBLAYOUT, SCHEMATIC, STRANGER, SYMBOLIC
1736 * we are only concerned about the viewType NETLIST.
1737 */
1738 INTBIG io_edviewType(void)
1739 {
1740 CHAR name[WORD+1], cname[WORD+1], view[WORD+1];
1741 NODEPROTO *proto;
1742
1743 /* get the viewType */
1744 if (io_edget_token(name, 0) == NULL)
1745 longjmp(io_edifgbl.env, LONGJMPEOF);
1746
1747 if (!namesame(name, x_("BEHAVIOR"))) io_edifgbl.active_view = VBEHAVIOR;
1748 else if (!namesame(name, x_("DOCUMENT"))) io_edifgbl.active_view = VDOCUMENT;
1749 else if (!namesame(name, x_("GRAPHIC")))
1750 {
1751 io_edifgbl.active_view = VGRAPHIC;
1752 estrcpy(view, x_(""));
1753 }
1754 else if (!namesame(name, x_("LOGICMODEL"))) io_edifgbl.active_view = VLOGICMODEL;
1755 else if (!namesame(name, x_("MASKLAYOUT")))
1756 {
1757 io_edifgbl.active_view = VMASKLAYOUT;
1758 estrcpy(view, x_("lay"));
1759 }
1760 else if (!namesame(name, x_("NETLIST")))
1761 {
1762 io_edifgbl.active_view = VNETLIST;
1763 estrcpy(view, x_("sch"));
1764 }
1765 else if (!namesame(name, x_("PCBLAYOUT"))) io_edifgbl.active_view = VPCBLAYOUT;
1766 else if (!namesame(name, x_("SCHEMATIC")))
1767 {
1768 io_edifgbl.active_view = VSCHEMATIC;
1769 estrcpy(view, x_("sch"));
1770 }
1771 else if (!namesame(name, x_("STRANGER"))) io_edifgbl.active_view = VSTRANGER;
1772 else if (!namesame(name, x_("SYMBOLIC"))) io_edifgbl.active_view = VSYMBOLIC;
1773
1774 /* immediately allocate MASKLAYOUT and VGRAPHIC viewtypes */
1775 if (io_edifgbl.active_view == VMASKLAYOUT || io_edifgbl.active_view == VGRAPHIC ||
1776 io_edifgbl.active_view == VNETLIST || io_edifgbl.active_view == VSCHEMATIC)
1777 {
1778 /* locate this in the list of cells */
1779 for (proto = io_edifgbl.library->firstnodeproto; proto != NONODEPROTO;
1780 proto = proto->nextnodeproto)
1781 {
1782 if (!namesame(proto->protoname, io_edifgbl.cell_name) &&
1783 !namesame(proto->cellview->sviewname, view)) break;
1784 }
1785 if (proto == NONODEPROTO)
1786 {
1787 /* allocate the cell */
1788 esnprintf(cname, WORD+1, x_("%s{%s}"), io_edifgbl.cell_name, view);
1789 proto = us_newnodeproto(cname, io_edifgbl.library);
1790 if (proto == NONODEPROTO) longjmp(io_edifgbl.env, LONGJMPNOMEM);
1791 proto->temp1 = 0;
1792 }
1793 else if (proto->temp1) io_edifgbl.ignoreblock = 1;
1794
1795 io_edifgbl.current_cell = proto;
1796 }
1797 else io_edifgbl.current_cell = NONODEPROTO;
1798
1799 /* add the name to the celltbl */
1800 if (io_edifgbl.celltbl_cnt == io_edifgbl.celltbl_sze)
1801 {
1802 io_edifgbl.celltbl_sze += 100;
1803 if (io_edifgbl.celltbl_cnt == 0)
1804 {
1805 io_edifgbl.celltbl = (NAMETABLE_PTR *)emalloc(sizeof (NAMETABLE_PTR) *
1806 io_edifgbl.celltbl_sze, io_tool->cluster);
1807 if (io_edifgbl.celltbl == (NAMETABLE_PTR *)0) RET_NOMEMORY();
1808 } else
1809 {
1810 NAMETABLE_PTR *newtbl;
1811 long i;
1812
1813 newtbl = (NAMETABLE_PTR *)emalloc(sizeof (NAMETABLE_PTR) * io_edifgbl.celltbl_sze,
1814 io_tool->cluster);
1815 if (newtbl == (NAMETABLE_PTR *)0) RET_NOMEMORY();
1816 for(i=0; i<io_edifgbl.celltbl_cnt; i++) newtbl[i] = io_edifgbl.celltbl[i];
1817 io_edifgbl.celltbl = newtbl;
1818 }
1819 }
1820 io_edifgbl.celltbl[io_edifgbl.celltbl_cnt] = (NAMETABLE_PTR)emalloc(sizeof (NAMETABLE),
1821 io_tool->cluster);
1822 if (io_edifgbl.celltbl[io_edifgbl.celltbl_cnt] == NONAMETABLE) RET_NOMEMORY();
1823 if (allocstring(&io_edifgbl.celltbl[io_edifgbl.celltbl_cnt]->original, io_edifgbl.cell_reference,
1824 io_tool->cluster)) RET_NOMEMORY();
1825 if (allocstring(&io_edifgbl.celltbl[io_edifgbl.celltbl_cnt]->replace, io_edifgbl.cell_name,
1826 io_tool->cluster)) RET_NOMEMORY();
1827
1828 /* now sort by name */
1829 esort(io_edifgbl.celltbl, ++(io_edifgbl.celltbl_cnt), sizeof (NAMETABLE_PTR),
1830 io_edcompare_name);
1831 return(0);
1832 }
1833
1834 /* contents: Indicates additional information about higher level blocks
1835 * initially verifies the appropriate state, ie
1836 * (view XXX (viewType Netlist)
1837 * (contents ...
1838 */
1839 INTBIG io_edcontents(void)
1840 {
1841 return(0);
1842 }
1843
1844 /* port: Define connection point for the cell, must be in INTERFACE */
1845 INTBIG io_edport(void)
1846 {
1847 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
1848 io_edifgbl.direction = INPUTE;
1849 io_edifgbl.port_reference[0] = 0;
1850 io_edifgbl.isarray = 0;
1851 io_edifgbl.arrayx = io_edifgbl.arrayy = 1;
1852 if (io_edcheck_name())
1853 {
1854 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
1855 (void)estrcpy(io_edifgbl.port_name, io_edifgbl.name);
1856 }
1857 return(0);
1858 }
1859
1860 /* direction: Set the direction of a port */
1861 INTBIG io_eddirection(void)
1862 {
1863 CHAR name[WORD+1];
1864
1865 /* get the direction */
1866 if (io_edget_token(name, 0) == NULL)
1867 longjmp(io_edifgbl.env, LONGJMPEOF);
1868
1869 if (!namesame(name, x_("INOUT"))) io_edifgbl.direction = INOUT; else
1870 if (!namesame(name, x_("INPUT"))) io_edifgbl.direction = INPUTE; else
1871 if (!namesame(name, x_("OUTPUT"))) io_edifgbl.direction = OUTPUTE;
1872 return(0);
1873 }
1874
1875 /* instance definition routines */
1876 /* instance: Indicates a new instance within the cell
1877 */
1878 INTBIG io_edinstance(void)
1879 {
1880 /* set the current geometry type */
1881 io_edfreeptlist();
1882 io_edifgbl.proto = NONODEPROTO;
1883 io_edifgbl.geometry = GINSTANCE;
1884 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
1885 io_edifgbl.orientation = OR0;
1886 io_edifgbl.isarray = 0;
1887 io_edifgbl.arrayx = io_edifgbl.arrayy = 1;
1888 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
1889 io_edifgbl.instance_reference[0] = 0;
1890 io_edifgbl.current_node = NONODEINST;
1891 if (io_edcheck_name())
1892 {
1893 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
1894 (void)estrcpy(io_edifgbl.instance_name, io_edifgbl.name);
1895 }
1896 return(0);
1897 }
1898
1899 INTBIG io_edarray(void)
1900 {
1901 /* note array is a special process integer value function */
1902 io_edifgbl.isarray = 1;
1903 io_edifgbl.arrayx = io_edifgbl.arrayy = 0;
1904 io_edifgbl.deltaxX = io_edifgbl.deltaxY = 0;
1905 io_edifgbl.deltayX = io_edifgbl.deltayY = 0;
1906 io_edifgbl.deltapts = 0;
1907 if (io_edcheck_name())
1908 {
1909 switch (kstack[kstack_ptr-1])
1910 {
1911 case KCELL:
1912 (void)estrcpy(io_edifgbl.cell_reference, io_edifgbl.name);
1913 (void)estrcpy(io_edifgbl.cell_name, io_edifgbl.name);
1914 break;
1915 case KPORT:
1916 (void)estrcpy(io_edifgbl.port_name, io_edifgbl.name);
1917 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
1918 break;
1919 case KINSTANCE:
1920 (void)estrcpy(io_edifgbl.instance_name, io_edifgbl.name);
1921 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
1922 break;
1923 case KNET:
1924 (void)estrcpy(io_edifgbl.net_reference, io_edifgbl.name);
1925 (void)estrcpy(io_edifgbl.net_name, io_edifgbl.name);
1926 break;
1927 case KPROPERTY:
1928 (void)estrcpy(io_edifgbl.property_reference, io_edifgbl.name);
1929 (void)estrcpy(io_edifgbl.property_name, io_edifgbl.name);
1930 break;
1931 default:
1932 break;
1933 }
1934 }
1935 return(0);
1936 }
1937
1938 INTBIG io_eddelta(void)
1939 {
1940 io_edifgbl.deltaxX = io_edifgbl.deltaxY = 0;
1941 io_edifgbl.deltayX = io_edifgbl.deltayY = 0;
1942 io_edifgbl.deltapts = 0;
1943 return(0);
1944 }
1945
1946 /* cellRef: determines the cell type of an instance
1947 */
1948 INTBIG io_edcellRef(void)
1949 {
1950 CHAR name[WORD+1], view[WORD+1];
1951 NODEPROTO *proto;
1952 INTBIG low, high, change, mid;
1953
1954 /* get the name of the cell */
1955 if (io_edget_token(name, 0) == NULL)
1956 longjmp(io_edifgbl.env, LONGJMPEOF);
1957
1958 switch (io_edifgbl.active_view)
1959 {
1960 case VMASKLAYOUT:
1961 estrcpy(view, x_("lay"));
1962 break;
1963 default:
1964 if (kstack[kstack_ptr - 1] == KDESIGN) estrcpy(view, x_("p1")); else
1965 estrcpy(view, x_("ic"));
1966 }
1967 if (io_edifgbl.vendor == EVVIEWLOGIC && !namesame(name, x_("SPLITTER")))
1968 {
1969 io_edifgbl.proto = NONODEPROTO;
1970 return(0);
1971 }
1972
1973 /* look for this cell name in the cell list */
1974 low = 0;
1975 high = io_edifgbl.celltbl_cnt - 1;
1976 while (low <= high)
1977 {
1978 mid = (low + high) / 2;
1979 change = namesame(name, io_edifgbl.celltbl[mid]->original);
1980 if (change < 0) high = mid - 1; else
1981 if (change > 0) low = mid + 1; else
1982 {
1983 /* found the name */
1984 (void)estrcpy(name, io_edifgbl.celltbl[mid]->replace);
1985 break;
1986 }
1987 }
1988 if (low > high)
1989 {
1990 ttyputerr(_("could not find cellRef <%s>"), name);
1991 }
1992
1993 /* now look for this cell in the list of cells, if not found create it */
1994 /* locate this in the list of cells */
1995 for (proto = io_edifgbl.library->firstnodeproto; proto != NONODEPROTO; proto = proto->nextnodeproto)
1996 {
1997 if (!namesame(proto->protoname, name) &&
1998 !namesame(proto->cellview->sviewname, view)) break;
1999 }
2000 if (proto == NONODEPROTO)
2001 {
2002 /* allocate the cell */
2003 if (view[0] != 0)
2004 {
2005 estrcat(name, x_("{"));
2006 estrcat(name, view);
2007 estrcat(name, x_("}"));
2008 }
2009 proto = us_newnodeproto(name, io_edifgbl.library);
2010 if (proto == NONODEPROTO) longjmp(io_edifgbl.env, LONGJMPNOMEM);
2011 proto->temp1 = 0;
2012 }
2013
2014 /* set the parent */
2015 io_edifgbl.proto = proto;
2016 return(0);
2017 }
2018
2019 INTBIG io_edinteger(void)
2020 {
2021 CHAR value[WORD+1];
2022
2023 if (io_edget_token(value, 0) == NULL)
2024 longjmp(io_edifgbl.env, LONGJMPEOF);
2025
2026 if (io_edifgbl.ptype == PSTRING) efree(io_edifgbl.pval.string);
2027 io_edifgbl.pval.integer = eatoi(value);
2028 io_edifgbl.ptype = PINTEGER;
2029 return(0);
2030 }
2031
2032 INTBIG io_ednumber(void)
2033 {
2034 if (io_edifgbl.ptype == PSTRING) efree(io_edifgbl.pval.string);
2035 io_edifgbl.pval.number = (float)io_edgetnumber();
2036 io_edifgbl.ptype = PNUMBER;
2037 return(0);
2038 }
2039
2040 INTBIG io_edstring(void)
2041 {
2042 CHAR *token, value[WORD+1];
2043
2044 if (*(token = io_edpos_token()) != '(' && *token != ')')
2045 {
2046 if (io_edget_token(value, 0) == NULL)
2047 longjmp(io_edifgbl.env, LONGJMPEOF);
2048 if (io_edifgbl.ptype == PSTRING) efree(io_edifgbl.pval.string);
2049
2050 value[estrlen(value) - 1] = 0;
2051 io_edifgbl.pval.string = (CHAR *)emalloc(estrlen(value) * SIZEOFCHAR, io_tool->cluster);
2052 if (io_edifgbl.pval.string == NULL)
2053 longjmp(io_edifgbl.env, LONGJMPNOMEM);
2054
2055 (void)estrcpy(io_edifgbl.pval.string, &value[1]);
2056 io_edifgbl.ptype = PSTRING;
2057 }
2058 return(0);
2059 }
2060
2061 INTBIG io_edproperty(void)
2062 {
2063 io_edifgbl.property_reference[0] = 0;
2064 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
2065 if (io_edifgbl.ptype == PSTRING) efree(io_edifgbl.pval.string);
2066 io_edifgbl.ptype = PUNKNOWN;
2067 if (io_edcheck_name())
2068 {
2069 (void)estrcpy(io_edifgbl.property_reference, io_edifgbl.name);
2070 (void)estrcpy(io_edifgbl.property_name, io_edifgbl.name);
2071 }
2072 return(0);
2073 }
2074
2075 /* net: Define a net name followed by edifgbl and local pin list
2076 * (net NAME
2077 * (joined
2078 * (portRef NAME (instanceRef NAME))
2079 * (portRef NAME)))
2080 */
2081 INTBIG io_ednet(void)
2082 {
2083 io_edifgbl.net_reference[0] = 0;
2084 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
2085 io_edifgbl.current_arc = NOARCINST;
2086 io_edifgbl.current_node = NONODEINST;
2087 io_edifgbl.current_port = NOPORTPROTO;
2088 io_edfreenetports();
2089 io_edifgbl.isarray = 0;
2090 io_edifgbl.arrayx = io_edifgbl.arrayy = 1;
2091 if (kstack[kstack_ptr-2] != KNETBUNDLE) io_edifgbl.geometry = GNET;
2092 if (io_edcheck_name())
2093 {
2094 (void)estrcpy(io_edifgbl.net_reference, io_edifgbl.name);
2095 (void)estrcpy(io_edifgbl.net_name, io_edifgbl.name);
2096 }
2097 return(0);
2098 }
2099
2100 INTBIG io_ednetBundle(void)
2101 {
2102 io_edifgbl.geometry = GBUS;
2103 io_edifgbl.bundle_reference[0] = 0;
2104 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
2105 io_edifgbl.isarray = 0;
2106 if (io_edcheck_name())
2107 {
2108 (void)estrcpy(io_edifgbl.bundle_reference, io_edifgbl.name);
2109 (void)estrcpy(io_edifgbl.bundle_name, io_edifgbl.name);
2110 }
2111 return(0);
2112 }
2113
2114 INTBIG io_edjoined(void)
2115 {
2116 return(0);
2117 }
2118
2119 /* portRef: specifies a pin on a net */
2120 INTBIG io_edportRef(void)
2121 {
2122 io_edifgbl.port_reference[0] = 0;
2123 io_edifgbl.instance_reference[0] = 0;
2124 if (io_edcheck_name())
2125 {
2126 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
2127 }
2128
2129 /* allocate a netport */
2130 if (io_edallocnetport())
2131 longjmp(io_edifgbl.env, LONGJMPNOMEM);
2132 return(0);
2133 }
2134
2135 /* instanceRef: identifies the name of the instance attached to the net */
2136 INTBIG io_edinstanceRef(void)
2137 {
2138 io_edifgbl.instance_reference[0] = 0;
2139 if (io_edcheck_name())
2140 {
2141 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
2142 }
2143 return(0);
2144 }
2145
2146 /* array member function, determines a specific element of an array */
2147 INTBIG io_edmember(void)
2148 {
2149 io_edifgbl.memberx = -1; /* no member */
2150 io_edifgbl.membery = -1; /* no member */
2151 if (io_edcheck_name())
2152 {
2153 switch (kstack[kstack_ptr-1])
2154 {
2155 case KPORTREF:
2156 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
2157 break;
2158 case KINSTANCEREF:
2159 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
2160 break;
2161 default:
2162 break;
2163 }
2164 }
2165 return(0);
2166 }
2167
2168 INTBIG io_edname(void)
2169 {
2170 INTBIG kptr;
2171
2172 if (kstack[kstack_ptr-1] == KARRAY || kstack[kstack_ptr-1] == KMEMBER) kptr = kstack_ptr-2; else
2173 kptr = kstack_ptr - 1;
2174 if (io_edcheck_name())
2175 {
2176 switch (kstack[kptr])
2177 {
2178 case KCELL:
2179 (void)estrcpy(io_edifgbl.cell_reference, io_edifgbl.name);
2180 (void)estrcpy(io_edifgbl.cell_name, io_edifgbl.name);
2181 break;
2182 case KPORTIMPLEMENTATION: /* added by smr */
2183 case KPORT:
2184 (void)estrcpy(io_edifgbl.port_name, io_edifgbl.name);
2185 /* FALLTHROUGH */
2186 case KPORTREF:
2187 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
2188 break;
2189 case KINSTANCE:
2190 (void)estrcpy(io_edifgbl.instance_name, io_edifgbl.name);
2191 /* FALLTHROUGH */
2192 case KINSTANCEREF:
2193 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
2194 break;
2195 case KNET:
2196 (void)estrcpy(io_edifgbl.net_reference, io_edifgbl.name);
2197 (void)estrcpy(io_edifgbl.net_name, io_edifgbl.name);
2198 break;
2199 case KPROPERTY:
2200 (void)estrcpy(io_edifgbl.property_reference, io_edifgbl.name);
2201 (void)estrcpy(io_edifgbl.property_name, io_edifgbl.name);
2202 break;
2203 default:
2204 break;
2205 }
2206
2207 /* init the point lists */
2208 io_edfreeptlist();
2209 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
2210 io_edifgbl.orientation = OR0;
2211 io_edifgbl.visible = 1;
2212 io_edifgbl.justification = LOWERLEFT;
2213 io_edifgbl.textheight = 0;
2214 (void)estrcpy(io_edifgbl.string, io_edifgbl.name);
2215 }
2216 return(0);
2217 }
2218
2219 INTBIG io_edrename(void)
2220 {
2221 CHAR name[WORD+1];
2222 INTBIG kptr;
2223
2224 /* get the name of the object */
2225 if (io_edget_token(name, 0) == NULL)
2226 longjmp(io_edifgbl.env, LONGJMPEOF);
2227 (void)estrcpy(io_edifgbl.name, (name[0] == '&') ? &name[1] : name);
2228
2229 /* and the original name */
2230 if (*io_edpos_token() == '(')
2231 {
2232 /* must be stringDisplay, copy name to original */
2233 (void)estrcpy(io_edifgbl.original, io_edifgbl.name);
2234 } else
2235 {
2236 if (io_edget_token(name, 0) == NULL)
2237 longjmp(io_edifgbl.env, LONGJMPEOF);
2238
2239 /* copy name without quotes */
2240 (void)estrcpy(io_edifgbl.original, &name[1]);
2241 io_edifgbl.original[estrlen(name)-2] = 0;
2242 }
2243 if (kstack[kstack_ptr - 1] == KNAME) kptr = kstack_ptr - 1; else
2244 kptr = kstack_ptr;
2245 if (kstack[kptr - 1] == KARRAY) kptr = kptr - 2; else
2246 kptr = kptr -1;
2247 switch (kstack[kptr])
2248 {
2249 case KCELL:
2250 (void)estrcpy(io_edifgbl.cell_reference, io_edifgbl.name);
2251 (void)estrcpy(io_edifgbl.cell_name, io_edifgbl.original);
2252 break;
2253 case KPORT:
2254 (void)estrcpy(io_edifgbl.port_reference, io_edifgbl.name);
2255 (void)estrcpy(io_edifgbl.port_name, io_edifgbl.original);
2256 break;
2257 case KINSTANCE:
2258 (void)estrcpy(io_edifgbl.instance_reference, io_edifgbl.name);
2259 (void)estrcpy(io_edifgbl.instance_name, io_edifgbl.original);
2260 break;
2261 case KNETBUNDLE:
2262 (void)estrcpy(io_edifgbl.bundle_reference, io_edifgbl.name);
2263 (void)estrcpy(io_edifgbl.bundle_name, io_edifgbl.original);
2264 break;
2265 case KNET:
2266 (void)estrcpy(io_edifgbl.net_reference, io_edifgbl.name);
2267 (void)estrcpy(io_edifgbl.net_name, io_edifgbl.original);
2268 break;
2269 case KPROPERTY:
2270 (void)estrcpy(io_edifgbl.property_reference, io_edifgbl.name);
2271 (void)estrcpy(io_edifgbl.property_name, io_edifgbl.original);
2272 break;
2273 default:
2274 break;
2275 }
2276 return(0);
2277 }
2278
2279 /* symbol routines and schematic routines */
2280 /* boundingBox - describes the bounding box of a schematic symbol */
2281 INTBIG io_edboundingBox(void)
2282 {
2283 io_edifgbl.figure_group = art_openeddottedpolygonprim;
2284 return(0);
2285 }
2286
2287 /* symbol - describes a schematic symbol */
2288 INTBIG io_edsymbol(void)
2289 {
2290 CHAR cname[WORD+1];
2291 NODEPROTO *proto;
2292 INTBIG center[2];
2293
2294 io_edifgbl.active_view = VSYMBOL;
2295
2296 /* locate this in the list of cells */
2297 for (proto = io_edifgbl.library->firstnodeproto; proto != NONODEPROTO; proto = proto->nextnodeproto)
2298 {
2299 if (!namesame(proto->protoname, io_edifgbl.cell_name) &&
2300 !namesame(proto->cellview->sviewname, x_("ic"))) break;
2301 }
2302 if (proto == NONODEPROTO)
2303 {
2304 /* allocate the cell */
2305 esnprintf(cname, WORD+1, x_("%s{ic}"), io_edifgbl.cell_name);
2306 proto = us_newnodeproto(cname, io_edifgbl.library);
2307 if (proto == NONODEPROTO) longjmp(io_edifgbl.env, LONGJMPNOMEM);
2308 proto->userbits |= WANTNEXPAND;
2309 proto->temp1 = 0;
2310 center[0] = center[1] = 0;
2311 (void)setvalkey((INTBIG)proto, VNODEPROTO, el_prototype_center_key,
2312 (INTBIG)center, VINTEGER|VISARRAY|(2<<VLENGTHSH));
2313
2314 }
2315 else if (proto->temp1) io_edifgbl.ignoreblock = 1;
2316
2317 io_edifgbl.current_cell = proto;
2318 io_edifgbl.figure_group = NONODEPROTO;
2319 return(0);
2320 }
2321
2322 INTBIG io_edportImplementation(void)
2323 {
2324 /* set the current geometry type */
2325 io_edfreeptlist();
2326 io_edifgbl.proto = sch_wirepinprim;
2327 io_edifgbl.geometry = GPIN;
2328 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
2329 io_edifgbl.orientation = OR0;
2330 io_edifgbl.isarray = 0;
2331 io_edifgbl.arrayx = io_edifgbl.arrayy = 1;
2332 io_edifgbl.name[0] = io_edifgbl.original[0] = 0;
2333 (void)io_edcheck_name();
2334 return(0);
2335 }
2336
2337 INTBIG io_edconnectLocation(void)
2338 {
2339 return(0);
2340 }
2341
2342 INTBIG io_edinterface(void)
2343 {
2344 NODEPROTO *np;
2345 CHAR nodename[WORD+1];
2346
2347 /* create schematic page 1 to represent all I/O for this schematic */
2348 /* locate this in the list of cells */
2349 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
2350 {
2351 if (!namesame(np->protoname, io_edifgbl.cell_name) &&
2352 !namesame(np->cellview->sviewname, x_("sch"))) break;
2353 }
2354 if (np == NONODEPROTO)
2355 {
2356 /* allocate the cell */
2357 esnprintf(nodename, WORD+1, x_("%s{sch}"), io_edifgbl.cell_name);
2358 io_edifgbl.current_cell = us_newnodeproto(nodename, io_edifgbl.library);
2359 if (io_edifgbl.current_cell == NONODEPROTO)
2360 longjmp(io_edifgbl.env, LONGJMPNOMEM);
2361 io_edifgbl.current_cell->temp1 = 0;
2362 }
2363 else io_edifgbl.current_cell = np;
2364
2365 /* now set the current position in the schematic page */
2366 io_edifgbl.ipos = io_edifgbl.bpos = io_edifgbl.opos = 0;
2367 return(0);
2368 }
2369
2370 INTBIG io_eddot(void)
2371 {
2372 io_edfreeptlist();
2373 io_edifgbl.points = io_edifgbl.lastpt = NOEPT;
2374 io_edifgbl.orientation = OR0;
2375 return(0);
2376 }
2377
2378 double io_edgetnumber(void)
2379 {
2380 CHAR value[WORD+1];
2381 INTBIG matissa, exponent;
2382
2383 if (io_edget_token(value, 0) == NULL)
2384 {
2385 longjmp(io_edifgbl.env, LONGJMPNOINT);
2386 }
2387 if (value[0] == '(')
2388 {
2389 /* must be in e notation */
2390 if (io_edget_token(value, 0) == NULL ||
2391 namesame(value, x_("e")))
2392 longjmp(io_edifgbl.env, LONGJMPILLNUM);
2393
2394 /* now the matissa */
2395 if (io_edget_token(value, 0) == NULL)
2396 longjmp(io_edifgbl.env, LONGJMPNOMANT);
2397 matissa = eatoi(value);
2398
2399 /* now the exponent */
2400 if (io_edget_token(value, 0) == NULL)
2401 longjmp(io_edifgbl.env, LONGJMPNOEXP);
2402 exponent = eatoi(value);
2403 io_edget_delim(')');
2404 return((double)matissa * pow(10.0, (double)exponent));
2405 }
2406 return((double) eatoi(value));
2407 }
2408
2409 INTBIG io_edcheck_name(void)
2410 {
2411 CHAR *pp;
2412 CHAR name[WORD+1];
2413
2414 if (*(pp = io_edpos_token()) != '(' && *pp != ')')
2415 {
2416 if (io_edget_token(name, 0) == NULL)
2417 longjmp(io_edifgbl.env, LONGJMPILLNAME);
2418 (void)estrcpy(io_edifgbl.name, (name[0] == '&') ? &name[1] : name);
2419 return(1);
2420 }
2421 return(0);
2422 }
2423
2424 static void io_edmake_electric_name(CHAR *ref, CHAR *name, int x, int y)
2425 {
2426 }
2427
2428 /* general utilities ... */
2429 static void io_edcheck_busnames(ARCINST *ai, CHAR *base)
2430 {
2431 PORTARCINST *pai;
2432 NODEINST *ni;
2433 INTBIG i, l;
2434 VARIABLE *var;
2435 CHAR *name, newname[WORD+1];
2436
2437 if (ai->proto != sch_busarc)
2438 {
2439 /* verify the name */
2440 var = getvalkey((INTBIG)ai, VARCINST, VSTRING, el_arc_name_key);
2441 if (var != NOVARIABLE && ((name = (CHAR *)var->addr) != NULL))
2442 {
2443 l = estrlen(base);
2444 if (!namesamen(name, base, l) && isdigit(name[l]))
2445 {
2446 (void)esnprintf(newname, WORD+1, x_("%s[%s]"), base, &name[l]);
2447 var = setvalkey((INTBIG)ai, VARCINST, el_arc_name_key, (INTBIG)newname, VSTRING);
2448 if (var != NOVARIABLE)
2449 defaulttextsize(4, var->textdescript);
2450 }
2451 }
2452 }
2453 ai->temp1 = 1;
2454 for (i = 0; i < 2; i++)
2455 {
2456 ni = ai->end[i].nodeinst;
2457 if (((ni->proto->userbits & NFUNCTION) >> NFUNCTIONSH) == NPPIN)
2458 {
2459 /* scan through this nodes portarcinst's */
2460 for (pai = ni->firstportarcinst; pai != NOPORTARCINST; pai = pai->nextportarcinst)
2461 {
2462 if (pai->conarcinst->temp1 == 0)
2463 io_edcheck_busnames(pai->conarcinst, base);
2464 }
2465 }
2466 }
2467 }
2468
2469 /* pop the keyword state stack, called when ')' is encountered. Note this function
2470 needs to broken into a simple function call structure. */
2471 #define MAXBUSPINS 256
2472 INTBIG io_edpop_stack(void)
2473 {
2474 INTBIG eindex, key, lambda;
2475 INTBIG lx, ly, hx, hy, cx, cy, cnt, Ix, Iy, gx, gy, xoff, yoff, dist;
2476 INTBIG *trace, *pt, pts[26], fcnt, tcnt, psx, psy;
2477 INTBIG width, height, x[3], y[3], radius, trans;
2478 INTBIG count, user_max, i, j, dup, fbus, tbus, instcount, instptx, instpty;
2479 UINTBIG descript[TEXTDESCRIPTSIZE];
2480 CHAR nodename[WORD+1], portname[WORD+1], basename[WORD+1], *name, orig[WORD+1];
2481 CHAR **layers, **layer_numbers;
2482 NODEPROTO *np, *nnp;
2483 ARCPROTO *ap, *lap;
2484 ARCINST *ai;
2485 PORTPROTO *ppt, *fpp, *lpp, *pp, *lastport;
2486 NODEINST *ni, *lastpin, *fni, *lni;
2487 EPT_PTR point;
2488 EDPROPERTY_PTR property, nproperty;
2489 double ar, so;
2490 VARIABLE *var;
2491 XARRAY rot;
2492 EDPORT_PTR eport, neport;
2493 /* bus connection variables */
2494 PORTPROTO *fpps[MAXBUSPINS], *tpps[MAXBUSPINS];
2495 NODEINST *fnis[MAXBUSPINS], *tnis[MAXBUSPINS];
2496 REGISTER void *infstr;
2497
2498 lambda = el_curlib->lambda[io_edifgbl.technology->techindex];
2499 if (kstack_ptr)
2500 {
2501 if (!io_edifgbl.ignoreblock)
2502 {
2503 switch (io_edifgbl.state)
2504 {
2505 case KFIGURE:
2506 io_edifgbl.cur_nametbl = NONAMETABLE;
2507 io_edifgbl.visible = 1;
2508 io_edifgbl.justification = LOWERLEFT;
2509 io_edifgbl.textheight = 0;
2510 break;
2511 case KBOUNDINGBOX:
2512 io_edifgbl.figure_group = NONODEPROTO;
2513 break;
2514 case KTECHNOLOGY:
2515 var = getval((INTBIG)io_edifgbl.technology, VTECHNOLOGY, VSTRING|VISARRAY,
2516 x_("IO_gds_layer_numbers"));
2517 if (var != NOVARIABLE)
2518 {
2519 layer_numbers = (CHAR **)var->addr;
2520 count = getlength(var);
2521 var = getval((INTBIG)io_edifgbl.technology, VTECHNOLOGY, VSTRING|VISARRAY,
2522 x_("TECH_layer_names"));
2523 if (var != NOVARIABLE)
2524 {
2525 layers = (CHAR **) var->addr;
2526 user_max = io_edifgbl.layer_ptr;
2527 /* for all layers assign their GDS number */
2528 for (i=0; i<count; i++)
2529 {
2530 if (*layer_numbers[i] != 0)
2531 {
2532 /* search for this layer */
2533 for (j=0; j<user_max; j++)
2534 {
2535 if (!namesame(io_edifgbl.nametbl[j]->replace, layers[i])) break;
2536 }
2537 if (user_max == j)
2538 {
2539 /* add to the list */
2540 io_edifgbl.nametbl[io_edifgbl.layer_ptr] = (NAMETABLE_PTR)
2541 emalloc(sizeof(NAMETABLE), io_tool->cluster);
2542 if (io_edifgbl.nametbl[io_edifgbl.layer_ptr] == NONAMETABLE) RET_NOMEMORY();
2543 if (allocstring(&io_edifgbl.nametbl[io_edifgbl.layer_ptr]->replace, layers[i],
2544 io_tool->cluster)) RET_NOMEMORY();
2545 esnprintf(orig, WORD+1, x_("layer_%s"), layer_numbers[i]);
2546 if (allocstring(&io_edifgbl.nametbl[io_edifgbl.layer_ptr]->original,
2547 orig, io_tool->cluster)) RET_NOMEMORY();
2548 io_edifgbl.nametbl[io_edifgbl.layer_ptr]->textheight = 0;
2549 io_edifgbl.nametbl[io_edifgbl.layer_ptr]->justification = LOWERLEFT;
2550 io_edifgbl.layer_ptr++;
2551 }
2552 }
2553 }
2554 }
2555 }
2556
2557 /* sort the layer list */
2558 esort(io_edifgbl.nametbl, io_edifgbl.layer_ptr, sizeof(NAMETABLE_PTR),
2559 io_edcompare_name);
2560
2561 /* now look for nodes to map MASK layers to */
2562 for (eindex = 0; eindex < io_edifgbl.layer_ptr; eindex++)
2563 {
2564 esnprintf(nodename, WORD+1, x_("%s-node"), io_edifgbl.nametbl[eindex]->replace);
2565 for (np = io_edifgbl.technology->firstnodeproto; np != NONODEPROTO;
2566 np = np->nextnodeproto)
2567 {
2568 if (!namesame(nodename, np->protoname)) break;
2569 }
2570 if (np == NONODEPROTO)
2571 {
2572 np = art_boxprim;
2573 }
2574 for (ap = io_edifgbl.technology->firstarcproto; ap != NOARCPROTO;
2575 ap = ap->nextarcproto)
2576 {
2577 if (!namesame(ap->protoname, io_edifgbl.nametbl[eindex]->replace))
2578 break;
2579 }
2580 io_edifgbl.nametbl[eindex]->node = np;
2581 io_edifgbl.nametbl[eindex]->arc = ap;
2582 }
2583 break;
2584 case KINTERFACE:
2585 if (io_edifgbl.active_view == VNETLIST)
2586 {
2587 /* create a black-box symbol at the current scale */
2588 np = io_edifgbl.current_cell;
2589 (void)esnprintf(nodename, WORD+1, x_("%s{ic}"), np->protoname);
2590 nnp = io_edmakeiconcell(np->firstportproto, np->protoname,
2591 nodename, io_edifgbl.library);
2592 if (nnp == NONODEPROTO)
2593 {
2594 ttyputerr(_("error, line #%d: could not create icon <%s>"),
2595 io_edifgbl.lineno, nodename);
2596 io_edifgbl.errors++;
2597 } else
2598 {
2599 /* now compute the bounds of this cell */
2600 db_boundcell(nnp, &nnp->lowx, &nnp->highx, &nnp->lowy, &nnp->highy);
2601 }
2602 }
2603 break;
2604 case KVIEW:
2605
2606 if (io_edifgbl.vendor == EVVIEWLOGIC && io_edifgbl.active_view != VNETLIST)
2607 {
2608 /* fixup incorrect bus nets */
2609 for (ai = io_edifgbl.current_cell->firstarcinst; ai != NOARCINST;
2610 ai = ai->nextarcinst)
2611 {
2612 ai->temp1 = ai->temp2 = 0;
2613 }
2614
2615 /* now scan for BUS nets, and verify all wires connected to bus */
2616 for (ai = io_edifgbl.current_cell->firstarcinst; ai != NOARCINST;
2617 ai = ai->nextarcinst)
2618 {
2619 if (ai->temp1 == 0 && ai->proto == sch_busarc)
2620 {
2621 /* get name of arc */
2622 var = getvalkey((INTBIG)ai, VARCINST, VSTRING, el_arc_name_key);
2623 if (var != NOVARIABLE && ((name = (CHAR *)var->addr) != NULL))
2624 {
2625 /* create the basename */
2626 (void)estrcpy(basename, name);
2627 name = estrrchr(basename, '[');
2628 if (name != NULL) *name = 0;
2629
2630 /* expand this arc, and locate non-bracketed names */
2631 io_edcheck_busnames(ai, basename);
2632 }
2633 }
2634 }
2635 }
2636
2637 /* move the port list to the free list */
2638 for (eport = io_edifgbl.ports; eport != NOEDPORT; eport = neport)
2639 {
2640 neport = eport->next;
2641 eport->next = io_edifgbl.free_ports;
2642 io_edifgbl.free_ports = eport;
2643 efree(eport->name);
2644 efree(eport->reference);
2645 }
2646 io_edifgbl.ports = NOEDPORT;
2647 break;
2648 case KPORT:
2649 if (io_edallocport()) return(1);
2650 eport = io_edifgbl.ports;
2651 np = io_edifgbl.current_cell;
2652 switch (eport->direction)
2653 {
2654 case INPUTE:
2655 cx = 0;
2656 cy = io_edifgbl.ipos;
2657 io_edifgbl.ipos += INCH;
2658 fpp = default_input;
2659 break;
2660 case INOUT:
2661 cx = 3*INCH;
2662 cy = io_edifgbl.bpos;
2663 io_edifgbl.bpos += INCH;
2664 fpp = default_input;
2665 break;
2666 case OUTPUTE:
2667 cx = 6*INCH;
2668 cy = io_edifgbl.opos;
2669 io_edifgbl.opos += INCH;
2670 fpp = default_output;
2671 break;
2672 }
2673
2674 /* now create the off-page reference */
2675 defaultnodesize(sch_offpageprim, &psx, &psy);
2676 ni = newnodeinst(sch_offpageprim,
2677 cx + (sch_offpageprim->lowx+sch_offpageprim->highx-psx)/2,
2678 cx + (sch_offpageprim->lowx+sch_offpageprim->highx+psx)/2,
2679 cy + (sch_offpageprim->lowy+sch_offpageprim->highy-psy)/2,
2680 cy + (sch_offpageprim->lowy+sch_offpageprim->highy+psy)/2, 0,0, np);
2681 if (ni == NONODEINST)
2682 {
2683 ttyputerr(_("error, line #%d: could not create external port"),
2684 io_edifgbl.lineno);
2685 io_edifgbl.errors++;
2686 break;
2687 }
2688
2689 /* now create the port */
2690 ppt = newportproto(ni->parent, ni, fpp, eport->name);
2691 if (ppt == NOPORTPROTO)
2692 {
2693 ttyputerr(_("error, line #%d: could not create port <%s>"),
2694 io_edifgbl.lineno, eport->name);
2695 io_edifgbl.errors++;
2696 } else
2697 {
2698 switch (eport->direction)
2699 {
2700 case INPUTE:
2701 ppt->userbits = (ppt->userbits & ~STATEBITS) | INPORT;
2702 break;
2703 case OUTPUTE:
2704 ppt->userbits = (ppt->userbits & ~STATEBITS) | OUTPORT;
2705 break;
2706 case INOUT:
2707 ppt->userbits = (ppt->userbits & ~STATEBITS) | BIDIRPORT;
2708 break;
2709 }
2710 }
2711 io_edifgbl.port_reference[0] = 0;
2712
2713 /* move the property list to the free list */
2714 for (property = io_edifgbl.properties; property != NOEDPROPERTY; property = nproperty)
2715 {
2716 key = makekey(property->name);
2717 switch (property->type)
2718 {
2719 case PINTEGER:
2720 var = setvalkey((INTBIG)ppt, VPORTPROTO, key, (INTBIG)property->val.integer,
2721 VINTEGER);
2722 break;
2723 case PNUMBER:
2724 var = setvalkey((INTBIG)ppt, VPORTPROTO, key, castint(property->val.number),
2725 VFLOAT);
2726 break;
2727 case PSTRING:
2728 var = setvalkey((INTBIG)ppt, VPORTPROTO, key, (INTBIG)property->val.string,
2729 VSTRING);
2730 break;
2731 default:
2732 break;
2733 }
2734 nproperty = property->next;
2735 property->next = io_edifgbl.free_properties;
2736 io_edifgbl.free_properties = property;
2737 efree(property->name);
2738 }
2739 io_edifgbl.properties = NOEDPROPERTY;
2740 break;
2741 case KINSTANCE:
2742 if (io_edifgbl.active_view == VNETLIST)
2743 {
2744 for (Ix = 0; Ix < io_edifgbl.arrayx; Ix++)
2745 {
2746 for (Iy = 0; Iy < io_edifgbl.arrayy; Iy++)
2747 {
2748 /* create this instance in the current sheet */
2749 width = io_edifgbl.proto->highx - io_edifgbl.proto->lowx;
2750 height = io_edifgbl.proto->highy - io_edifgbl.proto->lowy;
2751 width = (width + INCH - 1) / INCH;
2752 height = (height + INCH - 1) / INCH;
2753
2754 /* verify room for the icon */
2755 if (io_edifgbl.sh_xpos != -1)
2756 {
2757 if ((io_edifgbl.sh_ypos + (height + 1)) >=
2758 EDIF_sheet_bounds[io_edifgbl.sheet_size].height)
2759 {
2760 io_edifgbl.sh_ypos = 1;
2761 if ((io_edifgbl.sh_xpos += io_edifgbl.sh_offset) >=
2762 EDIF_sheet_bounds[io_edifgbl.sheet_size].width)
2763 io_edifgbl.sh_xpos = io_edifgbl.sh_ypos = -1; else
2764 io_edifgbl.sh_offset = 2;
2765 }
2766 }
2767 if (io_edifgbl.sh_xpos == -1)
2768 {
2769 /* create the new page */
2770 (void)esnprintf(nodename, WORD+1, x_("%s{p%d}"), io_edifgbl.cell_name,
2771 ++io_edifgbl.pageno);
2772 io_edifgbl.current_cell = np = us_newnodeproto(nodename, io_edifgbl.library);
2773 if (io_edifgbl.current_cell == NONODEPROTO)
2774 longjmp(io_edifgbl.env, LONGJMPNOMEM);
2775 np->temp1 = 0;
2776 io_edifgbl.sh_xpos = io_edifgbl.sh_ypos = 1;
2777 io_edifgbl.sh_offset = 2;
2778 }
2779
2780 /* create this instance */
2781 /* find out where true center moves */
2782 cx = ((io_edifgbl.proto->lowx+io_edifgbl.proto->highx) >> 1) +
2783 ((io_edifgbl.sh_xpos -
2784 (EDIF_sheet_bounds[io_edifgbl.sheet_size].width >> 1)) * INCH);
2785 cy = ((io_edifgbl.proto->lowy+io_edifgbl.proto->highy) >> 1) +
2786 ((io_edifgbl.sh_ypos -
2787 (EDIF_sheet_bounds[io_edifgbl.sheet_size].height >> 1)) * INCH);
2788 io_edifgbl.current_node = ni = newnodeinst(io_edifgbl.proto,
2789 io_edifgbl.proto->lowx + cx,
2790 io_edifgbl.proto->highx + cx,
2791 io_edifgbl.proto->lowy + cy,
2792 io_edifgbl.proto->highy + cy,
2793 io_edgettrans(io_edifgbl.orientation),
2794 io_edgetrot(io_edifgbl.orientation),
2795 io_edifgbl.current_cell);
2796 if (ni == NONODEINST)
2797 {
2798 ttyputerr(_("error, line #%d: could not create instance"),
2799 io_edifgbl.lineno);
2800 io_edifgbl.errors++;
2801 break;
2802 } else
2803 {
2804 if (io_edifgbl.proto->userbits & WANTNEXPAND)
2805 ni->userbits |= NEXPAND;
2806
2807 /* update the current position */
2808 if ((width + 2) > io_edifgbl.sh_offset)
2809 io_edifgbl.sh_offset = width + 2;
2810 if ((io_edifgbl.sh_ypos += (height + 1)) >=
2811 EDIF_sheet_bounds[io_edifgbl.sheet_size].height)
2812 {
2813 io_edifgbl.sh_ypos = 1;
2814 if ((io_edifgbl.sh_xpos += io_edifgbl.sh_offset) >=
2815 EDIF_sheet_bounds[io_edifgbl.sheet_size].width)
2816 io_edifgbl.sh_xpos = io_edifgbl.sh_ypos = -1; else
2817 io_edifgbl.sh_offset = 2;
2818 }
2819
2820 /* name the instance */
2821 if (io_edifgbl.instance_reference[0] != 0)
2822 {
2823 /* if single element or array with no offset */
2824 /* construct the representative extended EDIF name (includes [...]) */
2825 if ((io_edifgbl.arrayx == 1 && io_edifgbl.arrayy == 1) ||
2826 (io_edifgbl.deltaxX == 0 && io_edifgbl.deltaxY == 0 &&
2827 io_edifgbl.deltayX == 0 && io_edifgbl.deltayY == 0))
2828 (void)estrcpy(nodename, io_edifgbl.instance_reference);
2829 /* if array in the x dimension */
2830 else if (io_edifgbl.arrayx > 1)
2831 {
2832 if (io_edifgbl.arrayy > 1)
2833 (void)esnprintf(nodename, WORD+1, x_("%s[%ld,%ld]"),
2834 io_edifgbl.instance_reference, Ix, Iy);
2835 else
2836 (void)esnprintf(nodename, WORD+1, x_("%s[%ld]"),
2837 io_edifgbl.instance_reference, Ix);
2838 }
2839 /* if array in the y dimension */
2840 else if (io_edifgbl.arrayy > 1)
2841 (void)esnprintf(nodename, WORD+1, x_("%s[%ld]"),
2842 io_edifgbl.instance_reference, Iy);
2843
2844 /* check for array element descriptor */
2845 if (io_edifgbl.arrayx > 1 || io_edifgbl.arrayy > 1)
2846 {
2847 /* array descriptor is of the form index:index:range index:index:range */
2848 (void)esnprintf(basename, WORD+1, x_("%ld:%ld:%d %ld:%ld:%d"), Ix,
2849 (io_edifgbl.deltaxX == 0 && io_edifgbl.deltayX == 0) ?
2850 io_edifgbl.arrayx-1:Ix, io_edifgbl.arrayx, Iy,
2851 (io_edifgbl.deltaxY == 0 && io_edifgbl.deltayY == 0) ?
2852 io_edifgbl.arrayy-1:Iy, io_edifgbl.arrayy);
2853 var = setvalkey((INTBIG)ni, VNODEINST, EDIF_array_key, (INTBIG)basename,
2854 VSTRING);
2855
2856 }
2857
2858 /* now set the name of the component (note that Electric allows any string
2859 * of characters as a name, this name is open to the user, for ECO and other
2860 * consistancies, the EDIF_name is saved on a variable)
2861 */
2862 if (!namesame(io_edifgbl.instance_reference, io_edifgbl.instance_name))
2863 {
2864 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
2865 (INTBIG)nodename, VSTRING|VDISPLAY);
2866 if (var != NOVARIABLE)
2867 defaulttextsize(3, var->textdescript);
2868 } else
2869 {
2870 /* now add the original name as the displayed name (only to the first element) */
2871 if (Ix == 0 && Iy == 0)
2872 {
2873 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
2874 (INTBIG)io_edifgbl.instance_name, VSTRING|VDISPLAY);
2875 if (var != NOVARIABLE)
2876 defaulttextsize(3, var->textdescript);
2877 }
2878 /* now save the EDIF name (not displayed) */
2879 var = setvalkey((INTBIG)ni, VNODEINST, EDIF_name_key,
2880 (INTBIG)nodename, VSTRING);
2881 }
2882 }
2883 }
2884 }
2885 }
2886 }
2887
2888 /* move the property list to the free list */
2889 for (property = io_edifgbl.properties; property != NOEDPROPERTY; property = nproperty)
2890 {
2891 if (io_edifgbl.current_node != NONODEINST)
2892 {
2893 key = makekey(property->name);
2894 switch (property->type)
2895 {
2896 case PINTEGER:
2897 var = setvalkey((INTBIG)io_edifgbl.current_node, VNODEINST, key,
2898 (INTBIG)property->val.integer, VINTEGER);
2899 break;
2900 case PNUMBER:
2901 var = setvalkey((INTBIG)io_edifgbl.current_node, VNODEINST, key,
2902 castint(property->val.number), VFLOAT);
2903 break;
2904 case PSTRING:
2905 var = setvalkey((INTBIG)io_edifgbl.current_node, VNODEINST, key,
2906 (INTBIG)property->val.string, VSTRING);
2907 break;
2908 default:
2909 break;
2910 }
2911 }
2912 nproperty = property->next;
2913 property->next = io_edifgbl.free_properties;
2914 io_edifgbl.free_properties = property;
2915 efree(property->name);
2916 }
2917 io_edifgbl.properties = NOEDPROPERTY;
2918 io_edifgbl.instance_reference[0] = 0;
2919 io_edifgbl.current_node = NONODEINST;
2920 io_edfreesavedptlist();
2921 break;
2922 case KNET:
2923 /* move the property list to the free list */
2924 for (property = io_edifgbl.properties; property != NOEDPROPERTY; property = nproperty)
2925 {
2926 if (io_edifgbl.current_arc != NOARCINST)
2927 {
2928 key = makekey(property->name);
2929 switch (property->type)
2930 {
2931 case PINTEGER:
2932 var = setvalkey((INTBIG)io_edifgbl.current_arc, VARCINST, key,
2933 (INTBIG)property->val.integer, VINTEGER);
2934 break;
2935 case PNUMBER:
2936 var = setvalkey((INTBIG)io_edifgbl.current_arc, VARCINST, key,
2937 castint(property->val.number), VFLOAT);
2938 break;
2939 case PSTRING:
2940 var = setvalkey((INTBIG)io_edifgbl.current_arc, VARCINST, key,
2941 (INTBIG)property->val.string, VSTRING);
2942 break;
2943 default:
2944 break;
2945 }
2946 }
2947 nproperty = property->next;
2948 property->next = io_edifgbl.free_properties;
2949 io_edifgbl.free_properties = property;
2950 efree(property->name);
2951 }
2952 io_edifgbl.properties = NOEDPROPERTY;
2953 io_edifgbl.net_reference[0] = 0;
2954 io_edifgbl.current_arc = NOARCINST;
2955 if (io_edifgbl.geometry != GBUS)
2956 io_edifgbl.geometry = GUNKNOWN;
2957 io_edfreesavedptlist();
2958 break;
2959 case KNETBUNDLE:
2960 io_edifgbl.bundle_reference[0] = 0;
2961 io_edifgbl.current_arc = NOARCINST;
2962 io_edifgbl.geometry = GUNKNOWN;
2963 io_edfreesavedptlist();
2964 break;
2965 case KPROPERTY:
2966 if (io_edifgbl.active_view == VNETLIST || io_edifgbl.active_view == VSCHEMATIC)
2967 {
2968 /* add as a variable to the current object */
2969 i = 0;
2970 switch (kstack[kstack_ptr - 1])
2971 {
2972 case KINTERFACE:
2973 /* add to the {sch} view nodeproto */
2974 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO;
2975 np = np->nextnodeproto)
2976 {
2977 if (!namesame(np->protoname, io_edifgbl.cell_name) &&
2978 !namesame(np->cellview->sviewname, x_("sch"))) break;
2979 }
2980 if (np == NONODEPROTO)
2981 {
2982 /* allocate the cell */
2983 esnprintf(nodename, WORD+1, x_("%s{sch}"), io_edifgbl.cell_name);
2984 np = us_newnodeproto(nodename, io_edifgbl.library);
2985 if (np == NONODEPROTO) longjmp(io_edifgbl.env, LONGJMPNOMEM);
2986 np->temp1 = 0;
2987 }
2988 i = (INTBIG) np;
2989 j = VNODEPROTO;
2990 break;
2991 case KINSTANCE:
2992 case KNET:
2993 case KPORT:
2994 i = -1;
2995 break;
2996 default:
2997 i = 0;
2998 break;
2999 }
3000 if (i > 0)
3001 {
3002 key = makekey(io_edifgbl.property_reference);
3003 switch (io_edifgbl.ptype)
3004 {
3005 case PINTEGER:
3006 var = setvalkey(i, j, key, (INTBIG)io_edifgbl.pval.integer, VINTEGER);
3007 break;
3008 case PNUMBER:
3009 var = setvalkey(i, j, key, castint(io_edifgbl.pval.number), VFLOAT);
3010 break;
3011 case PSTRING:
3012 var = setvalkey(i, j, key, (INTBIG)io_edifgbl.pval.string, VSTRING);
3013 break;
3014 default:
3015 break;
3016 }
3017 } else if (i == -1)
3018 {
3019 /* add to the current property list, will be added latter */
3020 switch (io_edifgbl.ptype)
3021 {
3022 case PINTEGER:
3023 (void)io_edallocproperty(io_edifgbl.property_reference, io_edifgbl.ptype,
3024 (INTBIG)io_edifgbl.pval.integer, 0.0, NULL);
3025 break;
3026 case PNUMBER:
3027 (void)io_edallocproperty(io_edifgbl.property_reference, io_edifgbl.ptype,
3028 0, io_edifgbl.pval.number, NULL);
3029 break;
3030 case PSTRING:
3031 (void)io_edallocproperty(io_edifgbl.property_reference, io_edifgbl.ptype,
3032 0, 0.0, io_edifgbl.pval.string);
3033 break;
3034 default:
3035 break;
3036 }
3037 }
3038 }
3039 io_edifgbl.property_reference[0] = 0;
3040 io_edfreesavedptlist();
3041 break;
3042 case KPORTIMPLEMENTATION:
3043 io_edifgbl.geometry = GUNKNOWN;
3044 break;
3045 case KTRANSFORM:
3046 if (kstack_ptr <= 1 || kstack[kstack_ptr-1] != KINSTANCE)
3047 {
3048 io_edfreeptlist();
3049 break;
3050 }
3051
3052 /* get the corner offset */
3053 instcount = io_edifgbl.pt_count;
3054 if (instcount > 0)
3055 {
3056 instptx = io_edifgbl.points->x;
3057 instpty = io_edifgbl.points->y;
3058 }
3059
3060 /* if no points are specified, presume the origin */
3061 if (instcount == 0)
3062 {
3063 instptx = instpty = 0;
3064 instcount = 1;
3065 }
3066
3067 /* create node instance rotations about the origin not center */
3068 makeangle(io_edgetrot(io_edifgbl.orientation), io_edgettrans(io_edifgbl.orientation), rot);
3069
3070 if (instcount == 1 && io_edifgbl.proto != NONODEPROTO)
3071 {
3072 for (Ix = 0; Ix < io_edifgbl.arrayx; Ix++)
3073 {
3074 lx = instptx + Ix * io_edifgbl.deltaxX;
3075 ly = instpty + Ix * io_edifgbl.deltaxY;
3076 for (Iy = 0; Iy < io_edifgbl.arrayy; Iy++)
3077 {
3078 /* find out where true center moves */
3079 cx = (io_edifgbl.proto->lowx+io_edifgbl.proto->highx)/2;
3080 cy = (io_edifgbl.proto->lowy+io_edifgbl.proto->highy)/2;
3081 xform(cx, cy, &gx, &gy, rot);
3082
3083 /* now calculate the delta movement of the center */
3084 cx = gx - cx;
3085 cy = gy - cy;
3086 io_edifgbl.current_node = ni = newnodeinst(io_edifgbl.proto,
3087 lx + io_edifgbl.proto->lowx + cx,
3088 lx + io_edifgbl.proto->highx + cx,
3089 ly + io_edifgbl.proto->lowy + cy,
3090 ly + io_edifgbl.proto->highy + cy,
3091 io_edgettrans(io_edifgbl.orientation),
3092 io_edgetrot(io_edifgbl.orientation),
3093 io_edifgbl.current_cell);
3094 if (ni == NONODEINST)
3095 {
3096 ttyputerr(_("error, line #%d: could not create instance"),
3097 io_edifgbl.lineno);
3098 io_edifgbl.errors++;
3099
3100 /* and exit for loop */
3101 Ix = io_edifgbl.arrayx;
3102 Iy = io_edifgbl.arrayy;
3103 } else
3104 {
3105 if (io_edifgbl.proto->userbits & WANTNEXPAND)
3106 ni->userbits |= NEXPAND;
3107 }
3108 if (io_edifgbl.geometry == GPIN && lx == 0 && ly == 0)
3109 {
3110 /* determine an appropriate port name */
3111 (void)estrcpy(portname, io_edifgbl.port_name);
3112
3113 /* check if port already exists (will occur for multiple portImplementation statements */
3114 for (dup = 0, (void)estrcpy(basename, portname);
3115 (ppt = getportproto(ni->parent, portname)) != NOPORTPROTO;
3116 dup++)
3117 {
3118 if (dup == 0) pp = ppt;
3119 (void)esnprintf(portname, WORD+1, x_("%s_%ld"), basename, dup+1);
3120 }
3121
3122 /* only once */
3123 Ix = io_edifgbl.arrayx;
3124 Iy = io_edifgbl.arrayy;
3125 ppt = newportproto(ni->parent, ni, default_iconport, portname);
3126 if (ppt == NOPORTPROTO)
3127 {
3128 ttyputerr(_("error, line #%d: could not create port <%s>"),
3129 io_edifgbl.lineno, portname);
3130 io_edifgbl.errors++;
3131 } else
3132 {
3133 /* locate the direction of the port */
3134 for (eport = io_edifgbl.ports; eport != NOEDPORT; eport = eport->next)
3135 {
3136 if (!namesame(eport->reference, io_edifgbl.port_reference))
3137 {
3138 /* set the direction */
3139 switch (eport->direction)
3140 {
3141 case INPUTE:
3142 ppt->userbits = (ppt->userbits & ~STATEBITS) | INPORT;
3143 break;
3144 case OUTPUTE:
3145 ppt->userbits = (ppt->userbits & ~STATEBITS) | OUTPORT;
3146 break;
3147 case INOUT:
3148 ppt->userbits = (ppt->userbits & ~STATEBITS) | BIDIRPORT;
3149 break;
3150 }
3151 break;
3152 }
3153 }
3154 }
3155 } else
3156 {
3157 /* name the instance */
3158 if (io_edifgbl.instance_reference[0] != 0)
3159 {
3160 /* if single element or array with no offset */
3161 /* construct the representative extended EDIF name (includes [...]) */
3162 if ((io_edifgbl.arrayx == 1 && io_edifgbl.arrayy == 1) ||
3163 (io_edifgbl.deltaxX == 0 && io_edifgbl.deltaxY == 0 &&
3164 io_edifgbl.deltayX == 0 && io_edifgbl.deltayY == 0))
3165 (void)estrcpy(nodename, io_edifgbl.instance_reference);
3166 /* if array in the x dimension */
3167 else if (io_edifgbl.arrayx > 1)
3168 {
3169 if (io_edifgbl.arrayy > 1)
3170 (void)esnprintf(nodename, WORD+1, x_("%s[%ld,%ld]"),
3171 io_edifgbl.instance_reference, Ix, Iy);
3172 else
3173 (void)esnprintf(nodename, WORD+1, x_("%s[%ld]"),
3174 io_edifgbl.instance_reference, Ix);
3175 }
3176 /* if array in the y dimension */
3177 else if (io_edifgbl.arrayy > 1)
3178 (void)esnprintf(nodename, WORD+1, x_("%s[%ld]"),
3179 io_edifgbl.instance_reference, Iy);
3180
3181 /* check for array element descriptor */
3182 if (io_edifgbl.arrayx > 1 || io_edifgbl.arrayy > 1)
3183 {
3184 /* array descriptor is of the form index:index:range index:index:range */
3185 (void)esnprintf(basename, WORD+1, x_("%ld:%ld:%d %ld:%ld:%d"),
3186 Ix, (io_edifgbl.deltaxX == 0 && io_edifgbl.deltayX == 0) ? io_edifgbl.arrayx-1:Ix,
3187 io_edifgbl.arrayx, Iy,
3188 (io_edifgbl.deltaxY == 0 && io_edifgbl.deltayY == 0) ? io_edifgbl.arrayy-1:Iy,
3189 io_edifgbl.arrayy);
3190 var = setvalkey((INTBIG)ni, VNODEINST, EDIF_array_key, (INTBIG)basename,
3191 VSTRING);
3192 }
3193
3194 /* now set the name of the component (note that Electric allows any string
3195 * of characters as a name, this name is open to the user, for ECO and other
3196 * consistancies, the EDIF_name is saved on a variable)
3197 */
3198 if (!namesame(io_edifgbl.instance_reference, io_edifgbl.instance_name))
3199 {
3200 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
3201 (INTBIG)nodename, VSTRING|VDISPLAY);
3202 if (var != NOVARIABLE)
3203 defaulttextsize(3, var->textdescript);
3204 } else
3205 {
3206 /* now add the original name as the displayed name (only to the first element) */
3207 if (Ix == 0 && Iy == 0)
3208 {
3209 var = setvalkey((INTBIG)ni, VNODEINST, el_node_name_key,
3210 (INTBIG)io_edifgbl.instance_name, VSTRING|VDISPLAY);
3211 if (var != NOVARIABLE)
3212 defaulttextsize(3, var->textdescript);
3213 }
3214
3215 /* now save the EDIF name (not displayed) */
3216 var = setvalkey((INTBIG)ni, VNODEINST, EDIF_name_key,
3217 (INTBIG)nodename, VSTRING);
3218 }
3219
3220 /* now check for saved name attributes */
3221 if (io_edifgbl.save_text.points != NOEPT)
3222 {
3223 /* now set the position, relative to the center of the current object */
3224 xoff = io_edifgbl.save_text.points->x - ((ni->highx+ni->lowx)>>1);
3225 yoff = io_edifgbl.save_text.points->y - ((ni->highy+ni->lowy)>>1);
3226
3227 /* convert to quarter lambda units */
3228 xoff = 4*xoff / lambda;
3229 yoff = 4*yoff / lambda;
3230
3231 /*
3232 * determine the size of text, 0.0278 in == 2 points or 36 (2xpixels) == 1 in
3233 * fonts range from 4 to 20 points
3234 */
3235 if (io_edifgbl.save_text.textheight == 0) i = TXTSETQLAMBDA(4); else
3236 {
3237 i = io_ediftextsize(io_edifgbl.save_text.textheight);
3238 }
3239 TDCOPY(descript, var->textdescript);
3240 TDSETOFF(descript, xoff, yoff);
3241 TDSETSIZE(descript, i);
3242 TDSETPOS(descript, VTPOSCENT);
3243 switch (io_edifgbl.save_text.justification)
3244 {
3245 case UPPERLEFT:
3246 TDSETPOS(descript, VTPOSUPRIGHT);
3247 break;
3248 case UPPERCENTER:
3249 TDSETPOS(descript, VTPOSUP);
3250 break;
3251 case UPPERRIGHT:
3252 TDSETPOS(descript, VTPOSUPLEFT);
3253 break;
3254 case CENTERLEFT:
3255 TDSETPOS(descript, VTPOSRIGHT);
3256 break;
3257 case CENTERCENTER:
3258 TDSETPOS(descript, VTPOSCENT);
3259 break;
3260 case CENTERRIGHT:
3261 TDSETPOS(descript, VTPOSLEFT);
3262 break;
3263 case LOWERLEFT:
3264 TDSETPOS(descript, VTPOSDOWNRIGHT);
3265 break;
3266 case LOWERCENTER:
3267 TDSETPOS(descript, VTPOSDOWN);
3268 break;
3269 case LOWERRIGHT:
3270 TDSETPOS(descript, VTPOSDOWNLEFT);
3271 break;
3272 }
3273 TDCOPY(var->textdescript, descript);
3274 }
3275 }
3276 }
3277 if (io_edifgbl.deltayX == 0 && io_edifgbl.deltayY == 0) break;
3278
3279 /* bump the y delta and x deltas */
3280 lx += io_edifgbl.deltayX;
3281 ly += io_edifgbl.deltayY;
3282 }
3283 if (io_edifgbl.deltaxX == 0 && io_edifgbl.deltaxY == 0) break;
3284 }
3285 }
3286 io_edfreeptlist();
3287 break;
3288 case KPORTREF:
3289 /* check for the last pin */
3290 fni = io_edifgbl.current_node;
3291 fpp = io_edifgbl.current_port;
3292 if (io_edifgbl.port_reference[0] != 0)
3293 {
3294 /* For internal pins of an instance, determine the base port location and
3295 * other pin assignments
3296 */
3297 if (io_edifgbl.instance_reference[0] != 0)
3298 {
3299 (void)estrcpy(nodename, io_edifgbl.instance_reference);
3300
3301 /* locate the node and and port */
3302 if (io_edifgbl.active_view == VNETLIST)
3303 {
3304 /* scan all pages for this nodeinst */
3305 ni = NONODEINST;
3306 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3307 {
3308 if (namesame(np->protoname, io_edifgbl.cell_name) != 0) continue;
3309 for (ni = np->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
3310 {
3311 if ((var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, EDIF_name_key)) == NOVARIABLE &&
3312 (var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key)) == NOVARIABLE)
3313 continue;
3314 if (!namesame((CHAR *)var->addr, nodename)) break;
3315 }
3316 if (ni != NONODEINST) break;
3317 }
3318 if (ni == NONODEINST)
3319 {
3320 (void)ttyputmsg(_("error, line #%d: could not locate netlist node (%s)"),
3321 io_edifgbl.lineno, nodename);
3322 break;
3323 }
3324 ap = gen_unroutedarc;
3325 } else
3326 {
3327 /* net always references the current page */
3328 for (ni = io_edifgbl.current_cell->firstnodeinst; ni != NONODEINST;
3329 ni = ni->nextnodeinst)
3330 {
3331 if ((var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, EDIF_name_key)) == NOVARIABLE &&
3332 (var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, el_node_name_key)) == NOVARIABLE)
3333 continue;
3334 if (!namesame((CHAR *)var->addr, nodename)) break;
3335 }
3336 if (ni == NONODEINST)
3337 {
3338 (void)ttyputmsg(_("error, line #%d: could not locate schematic node '%s' in cell %s"),
3339 io_edifgbl.lineno, nodename, describenodeproto(io_edifgbl.current_cell));
3340 break;
3341 }
3342 if (io_edifgbl.isarray == 0) ap = sch_wirearc; else
3343 ap = sch_busarc;
3344 }
3345
3346 /* locate the port for this portref */
3347 pp = getportproto(ni->proto, io_edifgbl.port_reference);
3348 if (pp == NOPORTPROTO)
3349 {
3350 (void)ttyputmsg(_("error, line #%d: could not locate port (%s) on node (%s)"),
3351 io_edifgbl.lineno, io_edifgbl.port_reference, nodename);
3352 break;
3353 }
3354
3355 /* we have both, set global variable */
3356 io_edifgbl.current_node = ni;
3357 io_edifgbl.current_port = pp;
3358 np = ni->parent;
3359
3360 /* create extensions for net labels on single pin nets (externals), and
3361 * placeholder for auto-routing later
3362 */
3363 if (io_edifgbl.active_view == VNETLIST)
3364 {
3365 /* route all pins with an extension */
3366 if (ni != NONODEINST)
3367 {
3368 portposition(ni, pp, &hx, &hy);
3369 lx = hx;
3370 ly = hy;
3371 switch (pp->userbits&STATEBITS)
3372 {
3373 case INPORT:
3374 lx = hx - (INCH/10);
3375 break;
3376 case BIDIRPORT:
3377 ly = hy - (INCH/10);
3378 break;
3379 case OUTPORT:
3380 lx = hx + (INCH/10);
3381 break;
3382 }
3383
3384 /* need to create a destination for the wire */
3385 if (io_edifgbl.isarray != 0)
3386 {
3387 lni = io_edifiplacepin(sch_buspinprim, lx + sch_buspinprim->lowx,
3388 lx + sch_buspinprim->highx, ly + sch_buspinprim->lowy,
3389 ly + sch_buspinprim->highy, 0, 0, np);
3390 if (lni == NONODEINST)
3391 {
3392 ttyputmsg(_("error, line#%d: could not create bus pin"),
3393 io_edifgbl.lineno);
3394 break;
3395 }
3396 lpp = default_busport;
3397 lap = sch_busarc;
3398 } else
3399 {
3400 lni = io_edifiplacepin(sch_wirepinprim, lx + sch_wirepinprim->lowx,
3401 lx + sch_wirepinprim->highx, ly + sch_wirepinprim->lowy,
3402 ly + sch_wirepinprim->highy, 0, 0, np);
3403 if (lni == NONODEINST)
3404 {
3405 ttyputmsg(_("error, line#%d: could not create wire pin"),
3406 io_edifgbl.lineno);
3407 break;
3408 }
3409 lpp = default_port;
3410 lap = sch_wirearc;
3411 }
3412 io_edifgbl.current_arc = newarcinst(lap, defaultarcwidth(lap), CANTSLIDE,
3413 lni, lpp, lx, ly, ni, pp, hx, hy, np);
3414 if (io_edifgbl.current_arc == NOARCINST)
3415 ttyputmsg(_("error, line #%d: could not create auto-path"),
3416 io_edifgbl.lineno);
3417 else
3418 io_ednamearc(io_edifgbl.current_arc);
3419 }
3420 }
3421 } else
3422 {
3423 /* external port reference, look for a off-page reference in {sch} with this
3424 port name */
3425 for (np = io_edifgbl.library->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
3426 {
3427 if (namesame(np->protoname, io_edifgbl.cell_name) != 0) continue;
3428 if (np->cellview == el_schematicview) break;
3429 }
3430 if (np == NONODEPROTO)
3431 {
3432 ttyputmsg(_("error, line #%d: could not locate top level schematic"),
3433 io_edifgbl.lineno);
3434 break;
3435 }
3436
3437 /* now look for an instance with the correct port name */
3438 pp = getportproto(np, io_edifgbl.port_reference);
3439 if (pp == NOPORTPROTO)
3440 {
3441 if (io_edifgbl.original != 0 && *io_edifgbl.original != 0)
3442 pp = getportproto(np, io_edifgbl.original);
3443 if (pp == NOPORTPROTO)
3444 {
3445 ttyputmsg(_("error, line #%d: could not locate port '%s'"), io_edifgbl.lineno,
3446 io_edifgbl.port_reference);
3447 break;
3448 }
3449 }
3450 fni = pp->subnodeinst;
3451 fpp = pp->subportproto;
3452 portposition(fni, fpp, &lx, &ly);
3453
3454 /* determine x position by original placement */
3455 switch (pp->userbits&STATEBITS)
3456 {
3457 case INPORT:
3458 lx = 1*INCH;
3459 break;
3460 case BIDIRPORT:
3461 lx = 4*INCH;
3462 break;
3463 case OUTPORT:
3464 lx = 5*INCH;
3465 break;
3466 }
3467
3468 /* need to create a destination for the wire */
3469 if (io_edifgbl.isarray != 0)
3470 {
3471 ni = io_edifiplacepin(sch_buspinprim, lx + sch_buspinprim->lowx,
3472 lx + sch_buspinprim->highx, ly + sch_buspinprim->lowy,
3473 ly + sch_buspinprim->highy, 0, 0, np);
3474 if (ni == NONODEINST)
3475 {
3476 ttyputmsg(_("error, line#%d: could not create bus pin"),
3477 io_edifgbl.lineno);
3478 break;
3479 }
3480 pp = default_busport;
3481 } else
3482 {
3483 ni = io_edifiplacepin(sch_wirepinprim, lx + sch_wirepinprim->lowx,
3484 lx + sch_wirepinprim->highx, ly + sch_wirepinprim->lowy,
3485 ly + sch_wirepinprim->highy, 0, 0, np);
3486 if (ni == NONODEINST)
3487 {
3488 ttyputmsg(_("error, line#%d: could not create wire pin"),
3489 io_edifgbl.lineno);
3490 break;
3491 }
3492 pp = default_port;
3493 }
3494 if (io_edifgbl.isarray == 0) ap = sch_wirearc; else
3495 ap = sch_busarc;
3496 }
3497
3498 /* now connect if we have from node and port */
3499 if (fni != NONODEINST && fpp != NOPORTPROTO)
3500 {
3501 if (fni->parent != ni->parent)
3502 {
3503 ttyputmsg(_("error, line #%d: could not create path (arc) between cells %s and %s"),
3504 io_edifgbl.lineno, describenodeproto(fni->parent), describenodeproto(ni->parent));
3505 } else
3506 {
3507 /* locate the position of the new ports */
3508 portposition(fni, fpp, &lx, &ly);
3509 portposition(ni, pp, &hx, &hy);
3510
3511 /* for nets with no physical representation ... */
3512 io_edifgbl.current_arc = NOARCINST;
3513 if (lx == hx && ly == hy) dist = 0; else
3514 dist = computedistance(lx, ly, hx, hy);
3515 if (dist <= lambda*SLOPDISTANCE)
3516 {
3517 io_edifgbl.current_arc = newarcinst(ap, defaultarcwidth(ap),
3518 FIXANG|CANTSLIDE, fni, fpp, lx, ly, ni, pp, hx, hy, np);
3519 if (io_edifgbl.current_arc == NOARCINST)
3520 {
3521 ttyputmsg(_("error, line #%d: could not create path (arc)"),
3522 io_edifgbl.lineno);
3523 }
3524 }
3525 /* use unrouted connection for NETLIST views */
3526 else if (io_edifgbl.active_view == VNETLIST)
3527 {
3528 io_edifgbl.current_arc = newarcinst(ap, defaultarcwidth(ap),
3529 CANTSLIDE, fni, fpp, lx, ly, ni, pp, hx, hy, np);
3530 if (io_edifgbl.current_arc == NOARCINST)
3531 {
3532 ttyputmsg(_("error, line #%d: could not create auto-path"),
3533 io_edifgbl.lineno);
3534 }
3535 }
3536
3537 /* add the net name */
3538 if (io_edifgbl.current_arc != NOARCINST)
3539 io_ednamearc(io_edifgbl.current_arc);
3540 }
3541 }
3542 }
3543 break;
3544 case KINSTANCEREF:
3545 break;
3546 case KPATH:
3547 /* check for openShape type path */
3548 if (io_edifgbl.path_width == 0 &&
3549 io_edifgbl.geometry != GNET && io_edifgbl.geometry != GBUS) goto dopoly;
3550 fcnt = 0;
3551 if (io_edifgbl.geometry == GBUS || io_edifgbl.isarray) np = sch_buspinprim;
3552 else np = sch_wirepinprim;
3553 if (io_edifgbl.points == NOEPT) break;
3554 for (point = io_edifgbl.points; point->nextpt != NOEPT; point = point->nextpt)
3555 {
3556 if (io_edifgbl.geometry == GNET || io_edifgbl.geometry == GBUS)
3557 {
3558 /* create a pin to pin connection */
3559 if (fcnt == 0)
3560 {
3561 /* look for the first pin */
3562 fcnt = io_edfindport(io_edifgbl.current_cell, point->x,
3563 point->y, sch_wirearc, fnis, fpps);
3564 if (fcnt == 0)
3565 {
3566 /* create the "from" pin */
3567 fnis[0] = io_edifiplacepin(np, point->x + np->lowx, point->x + np->highx,
3568 point->y + np->lowy, point->y + np->highy,
3569 0, 0, io_edifgbl.current_cell);
3570 if (fnis[0] == NONODEINST) fcnt = 0; else
3571 {
3572 fpps[0] = (io_edifgbl.geometry == GBUS || io_edifgbl.isarray) ?
3573 default_busport : default_port;
3574 fcnt = 1;
3575 }
3576 }
3577 }
3578 /* now the second ... */
3579 tcnt = io_edfindport(io_edifgbl.current_cell, point->nextpt->x,
3580 point->nextpt->y, sch_wirearc, tnis, tpps);
3581 if (tcnt == 0)
3582 {
3583 /* create the "to" pin */
3584 tnis[0] = io_edifiplacepin(np, point->nextpt->x + np->lowx,
3585 point->nextpt->x + np->highx,
3586 point->nextpt->y + np->lowy,
3587 point->nextpt->y + np->highy,
3588 0, 0, io_edifgbl.current_cell);
3589 if (tnis[0] == NONODEINST) tcnt = 0; else
3590 {
3591 tpps[0] = (io_edifgbl.geometry == GBUS || io_edifgbl.isarray) ?
3592 default_busport : default_port;
3593 tcnt = 1;
3594 }
3595 }
3596
3597 if (tcnt == 0 || fcnt == 0)
3598 {
3599 ttyputerr(_("error, line #%d: could not create path"), io_edifgbl.lineno);
3600 io_edifgbl.errors++;
3601 } else
3602 {
3603 /* connect it */
3604 for (count = 0; count < fcnt || count < tcnt; count++)
3605 {
3606 if (count < fcnt)
3607 {
3608 lastpin = fnis[count];
3609 lastport = fpps[count];
3610
3611 /* check node for array variable */
3612 var = getvalkey((INTBIG)lastpin, VNODEINST, VSTRING, EDIF_array_key);
3613 if (var != NOVARIABLE) fbus = 1; else
3614 if (lastport->protoname[estrlen(lastport->protoname)-1] == ']') fbus = 1; else
3615 fbus = 0;
3616 }
3617 if (count < tcnt)
3618 {
3619 ni = tnis[count];
3620 pp = tpps[count];
3621
3622 /* check node for array variable */
3623 var = getvalkey((INTBIG)ni, VNODEINST, VSTRING, EDIF_array_key);
3624 if (var != NOVARIABLE) tbus = 1; else
3625 if (pp->protoname[estrlen(pp->protoname)-1] == ']') tbus = 1; else
3626 tbus = 0;
3627 }
3628
3629 /* if bus to bus */
3630 if ((lastport == default_busport || fbus) &&
3631 (pp == default_busport || tbus)) ap = sch_busarc;
3632 /* wire to other */
3633 else ap = sch_wirearc;
3634
3635 ai = newarcinst(ap, defaultarcwidth(ap), FIXANG|CANTSLIDE,
3636 lastpin, lastport, point->x, point->y,
3637 ni, pp, point->nextpt->x, point->nextpt->y,
3638 io_edifgbl.current_cell);
3639 if (ai == NOARCINST)
3640 {
3641 ttyputerr(_("error, line #%d: could not create path (arc)"),
3642 io_edifgbl.lineno);
3643 io_edifgbl.errors++;
3644 } else if (io_edifgbl.geometry == GNET && io_edifgbl.points == point)
3645 {
3646 if (io_edifgbl.net_reference)
3647 {
3648 var = setvalkey((INTBIG)ai, VARCINST, EDIF_name_key,
3649 (INTBIG)io_edifgbl.net_reference, VSTRING);
3650 }
3651 if (io_edifgbl.net_name)
3652 {
3653 /* set name of arc but don't display name */
3654 var = setvalkey((INTBIG)ai, VARCINST, el_arc_name_key,
3655 (INTBIG)io_edifgbl.net_name, VSTRING);
3656 if (var != NOVARIABLE)
3657 defaulttextsize(4, var->textdescript);
3658 }
3659 } else if (io_edifgbl.geometry == GBUS && io_edifgbl.points == point)
3660 {
3661 if (io_edifgbl.bundle_reference)
3662 {
3663 var = setvalkey((INTBIG)ai, VARCINST, EDIF_name_key,
3664 (INTBIG)io_edifgbl.bundle_reference, VSTRING);
3665 }
3666 if (io_edifgbl.bundle_name)
3667 {
3668 /* set bus' EDIF name but don't display name */
3669 var = setvalkey((INTBIG)ai, VARCINST, el_arc_name_key,
3670 (INTBIG)io_edifgbl.bundle_name, VSTRING);
3671 if (var != NOVARIABLE)
3672 defaulttextsize(4, var->textdescript);
3673 }
3674 }
3675 }
3676 if (ai != NOARCINST) io_edifgbl.current_arc = ai;
3677 for (count = 0; count < tcnt; count++)
3678 {
3679 fnis[count] = tnis[count];
3680 fpps[count] = tpps[count];
3681 }
3682 fcnt = tcnt;
3683 }
3684 } else
3685 {
3686 /* rectalinear paths with some width */
3687 /* create a path from here to there (orthogonal only now) */
3688 lx = hx = point->x;
3689 ly = hy = point->y;
3690 if (lx > point->nextpt->x) lx = point->nextpt->x;
3691 if (hx < point->nextpt->x) hx = point->nextpt->x;
3692 if (ly > point->nextpt->y) ly = point->nextpt->y;
3693 if (hy < point->nextpt->y) hy = point->nextpt->y;
3694 if (ly == hy || io_edifgbl.extend_end)
3695 {
3696 ly -= io_edifgbl.path_width/2;
3697 hy += io_edifgbl.path_width/2;
3698 }
3699 if (lx == hx || io_edifgbl.extend_end)
3700 {
3701 lx -= io_edifgbl.path_width/2;
3702 hx += io_edifgbl.path_width/2;
3703 }
3704 ni = io_edifiplacepin(io_edifgbl.figure_group, lx, hx, ly, hy,
3705 io_edgettrans(io_edifgbl.orientation),
3706 io_edgetrot(io_edifgbl.orientation),
3707 io_edifgbl.current_cell);
3708 if (ni == NONODEINST)
3709 {
3710 ttyputerr(_("error, line #%d: could not create path"),
3711 io_edifgbl.lineno);
3712 io_edifgbl.errors++;
3713 }
3714 }
3715 }
3716 io_edfreeptlist();
3717 break;
3718 case KCIRCLE:
3719 if (io_edifgbl.pt_count == 2)
3720 {
3721 lx = mini(io_edifgbl.points->x, io_edifgbl.lastpt->x);
3722 hx = maxi(io_edifgbl.points->x, io_edifgbl.lastpt->x);
3723 ly = mini(io_edifgbl.points->y, io_edifgbl.lastpt->y);
3724 hy = maxi(io_edifgbl.points->y, io_edifgbl.lastpt->y);
3725 if (lx == hx)
3726 {
3727 lx -= (hy - ly)>>1;
3728 hx += (hy - ly)>>1;
3729 } else
3730 {
3731 ly -= (hx - lx)>>1;
3732 hy += (hx - lx)>>1;
3733 }
3734
3735 /* create the node instance */
3736 ni = newnodeinst(art_circleprim, lx, hx, ly, hy,
3737 io_edgettrans(io_edifgbl.orientation),
3738 io_edgetrot(io_edifgbl.orientation),
3739 io_edifgbl.current_cell);
3740 if (ni == NONODEINST)
3741 {
3742 ttyputerr(_("error, line #%d: could not create circle"),
3743 io_edifgbl.lineno);
3744 io_edifgbl.errors++;
3745 }
3746 }
3747 io_edfreeptlist();
3748 break;
3749 case KNAME:
3750 /* save the data and break */
3751 io_edfreesavedptlist();
3752 (void)estrcpy(io_edifgbl.save_text.string, io_edifgbl.string);
3753 io_edifgbl.string[0] = 0;
3754 io_edifgbl.save_text.points = io_edifgbl.points;
3755 io_edifgbl.points = NOEPT;
3756 io_edifgbl.save_text.pt_count = io_edifgbl.pt_count;
3757 io_edifgbl.pt_count = 0;
3758 io_edifgbl.save_text.textheight = io_edifgbl.textheight;
3759 io_edifgbl.textheight = 0;
3760 io_edifgbl.save_text.justification = io_edifgbl.justification;
3761 io_edifgbl.justification = LOWERLEFT;
3762 io_edifgbl.save_text.orientation = io_edifgbl.orientation;
3763 io_edifgbl.orientation = OR0;
3764 io_edifgbl.save_text.visible = io_edifgbl.visible;
3765 io_edifgbl.visible = 1;
3766 break;
3767 case KSTRINGDISPLAY:
3768 if (kstack_ptr <= 1)
3769 {
3770 ttyputerr(_("error, line #%d: bad location for \"stringDisplay\""),
3771 io_edifgbl.lineno);
3772 io_edifgbl.errors++;
3773 }
3774 else if (kstack[kstack_ptr-1] == KRENAME)
3775 {
3776 /* save the data and break */
3777 io_edfreesavedptlist();
3778 (void)estrcpy(io_edifgbl.save_text.string, io_edifgbl.string);
3779 io_edifgbl.string[0] = 0;
3780 io_edifgbl.save_text.points = io_edifgbl.points;
3781 io_edifgbl.points = NOEPT;
3782 io_edifgbl.save_text.pt_count = io_edifgbl.pt_count;
3783 io_edifgbl.pt_count = 0;
3784 io_edifgbl.save_text.textheight = io_edifgbl.textheight;
3785 io_edifgbl.textheight = 0;
3786 io_edifgbl.save_text.justification = io_edifgbl.justification;
3787 io_edifgbl.justification = LOWERLEFT;
3788 io_edifgbl.save_text.orientation = io_edifgbl.orientation;
3789 io_edifgbl.orientation = OR0;
3790 io_edifgbl.save_text.visible = io_edifgbl.visible;
3791 io_edifgbl.visible = 1;
3792 }
3793
3794 /* output the data for annotate (display graphics) and string (on properties) */
3795 else if (kstack[kstack_ptr-1] == KANNOTATE || kstack[kstack_ptr-1] == KSTRING)
3796 {
3797 #ifdef IGNORESTRINGSWITHSQUAREBRACKETS
3798 /* supress this if it starts with "[" */
3799 if (io_edifgbl.string[0] != '[' && io_edifgbl.points != 0)
3800 #endif
3801 {
3802 /* see if a pre-existing node or arc exists to add text */
3803 ai = NOARCINST;
3804 ni = NONODEINST;
3805 if (io_edifgbl.property_reference[0] != 0 && io_edifgbl.current_node != NONODEINST)
3806 {
3807 ni = io_edifgbl.current_node;
3808 key = makekey(io_edifgbl.property_reference);
3809 xoff = io_edifgbl.points->x - ((ni->highx+ni->lowx)>>1);
3810 yoff = io_edifgbl.points->y - ((ni->highy+ni->lowy)>>1);
3811 }
3812 else if (io_edifgbl.property_reference[0] != 0 && io_edifgbl.current_arc != NOARCINST)
3813 {
3814 ai = io_edifgbl.current_arc;
3815 key = makekey(io_edifgbl.property_reference);
3816 xoff = io_edifgbl.points->x - ((ai->end[0].xpos + ai->end[1].xpos)>>1);
3817 yoff = io_edifgbl.points->y - ((ai->end[0].ypos + ai->end[1].ypos)>>1);
3818 } else
3819 {
3820 /* create the node instance */
3821 xoff = yoff = 0;
3822 ni = newnodeinst(gen_invispinprim,
3823 io_edifgbl.points->x, io_edifgbl.points->x,
3824 io_edifgbl.points->y, io_edifgbl.points->y, 0, 0,
3825 io_edifgbl.current_cell);
3826 key = EDIF_annotate_key;
3827 }
3828 if (ni != NONODEINST || ai != NOARCINST)
3829 {
3830 if (ni != NONODEINST)
3831 {
3832 var = setvalkey((INTBIG)ni, VNODEINST, key, (INTBIG)io_edifgbl.string,
3833 (io_edifgbl.visible ? VSTRING|VDISPLAY : VSTRING));
3834
3835 /* now set the position, relative to the center of the current object */
3836 xoff = io_edifgbl.points->x - ((ni->highx+ni->lowx)>>1);
3837 yoff = io_edifgbl.points->y - ((ni->highy+ni->lowy)>>1);
3838 } else
3839 {
3840 var = setvalkey((INTBIG)ai, VARCINST, key, (INTBIG)io_edifgbl.string,
3841 (io_edifgbl.visible ? VSTRING|VDISPLAY : VSTRING));
3842
3843 /* now set the position, relative to the center of the current object */
3844 xoff = io_edifgbl.points->x - ((ai->end[0].xpos + ai->end[1].xpos)>>1);
3845 yoff = io_edifgbl.points->y - ((ai->end[0].ypos + ai->end[1].ypos)>>1);
3846 }
3847
3848 /* convert to quarter lambda units */
3849 xoff = 4*xoff / lambda;
3850 yoff = 4*yoff / lambda;
3851
3852 /* determine the size of text, 0.0278 in == 2 points or 36 (2xpixels) == 1 in
3853 fonts range from 4 to 31 */
3854 if (io_edifgbl.textheight == 0) i = TXTSETQLAMBDA(4); else
3855 {
3856 i = io_ediftextsize(io_edifgbl.textheight);
3857 }
3858 TDCOPY(descript, var->textdescript);
3859 TDSETSIZE(descript, i);
3860 TDSETOFF(descript, xoff, yoff);
3861 TDSETPOS(descript, VTPOSCENT);
3862 switch (io_edifgbl.justification)
3863 {
3864 case UPPERLEFT: TDSETPOS(descript, VTPOSUPRIGHT); break;
3865 case UPPERCENTER: TDSETPOS(descript, VTPOSUP); break;
3866 case UPPERRIGHT: TDSETPOS(descript, VTPOSUPLEFT); break;
3867 case CENTERLEFT: TDSETPOS(descript, VTPOSRIGHT); break;
3868 case CENTERCENTER: TDSETPOS(descript, VTPOSCENT); break;
3869 case CENTERRIGHT: TDSETPOS(descript, VTPOSLEFT); break;
3870 case LOWERLEFT: TDSETPOS(descript, VTPOSDOWNRIGHT); break;
3871 case LOWERCENTER: TDSETPOS(descript, VTPOSDOWN); break;
3872 case LOWERRIGHT: TDSETPOS(descript, VTPOSDOWNLEFT); break;
3873 }
3874 TDCOPY(var->textdescript, descript);
3875 } else
3876 {
3877 ttyputerr(_("error, line #%d: nothing to attach text to"), io_edifgbl.lineno);
3878 io_edifgbl.errors++;
3879 }
3880 }
3881 }
3882
3883 /* clean up DISPLAY attributes */
3884 io_edfreeptlist();
3885 io_edifgbl.cur_nametbl = NONAMETABLE;
3886 io_edifgbl.visible = 1;
3887 io_edifgbl.justification = LOWERLEFT;
3888 io_edifgbl.textheight = 0;
3889 break;
3890 case KDOT:
3891 if (io_edifgbl.geometry == GPIN)
3892 {
3893 for (eport = io_edifgbl.ports; eport != NOEDPORT; eport = eport->next)
3894 {
3895 if (!namesame(eport->reference, io_edifgbl.name)) break;
3896 }
3897 if (eport != NOEDPORT)
3898 {
3899 /* create a internal wire port using the pin-proto, and create the port
3900 and export */
3901 ni = io_edifiplacepin(io_edifgbl.proto,
3902 io_edifgbl.points->x+io_edifgbl.proto->lowx,
3903 io_edifgbl.points->x+io_edifgbl.proto->highx,
3904 io_edifgbl.points->y+io_edifgbl.proto->lowy,
3905 io_edifgbl.points->y+io_edifgbl.proto->highy,
3906 io_edgettrans(io_edifgbl.orientation),
3907 io_edgetrot(io_edifgbl.orientation),
3908 io_edifgbl.current_cell);
3909 if (ni == NONODEINST)
3910 {
3911 ttyputerr(_("error, line #%d: could not create pin"), io_edifgbl.lineno);
3912 io_edifgbl.errors++;
3913 }
3914 (void)estrcpy(portname, eport->name);
3915 for (dup = 0, (void)estrcpy(basename, portname);
3916 (ppt = getportproto(ni->parent, portname)) != NOPORTPROTO; dup++)
3917 {
3918 if (dup == 0) pp = ppt;
3919 (void)esnprintf(portname, WORD+1, x_("%s_%ld"), basename, dup+1);
3920 }
3921 ppt = newportproto(ni->parent, ni, default_iconport, portname);
3922 if (ppt == NOPORTPROTO)
3923 {
3924 ttyputerr(_("error, line #%d: could not create port <%s>"),
3925 io_edifgbl.lineno, portname);
3926 io_edifgbl.errors++;
3927 } else
3928 {
3929 /* set the direction */
3930 switch (eport->direction)
3931 {
3932 case INPUTE:
3933 ppt->userbits = (ppt->userbits & ~STATEBITS) | INPORT;
3934 break;
3935 case OUTPUTE:
3936 ppt->userbits = (ppt->userbits & ~STATEBITS) | OUTPORT;
3937 break;
3938 case INOUT:
3939 ppt->userbits = (ppt->userbits & ~STATEBITS) | BIDIRPORT;
3940 break;
3941 }
3942 }
3943 }
3944 } else
3945 {
3946 /* create the node instance */
3947 ni = newnodeinst(io_edifgbl.figure_group != NONODEPROTO ?
3948 io_edifgbl.figure_group : art_boxprim,
3949 io_edifgbl.points->x, io_edifgbl.points->x,
3950 io_edifgbl.points->y, io_edifgbl.points->y,
3951 io_edgettrans(io_edifgbl.orientation),
3952 io_edgetrot(io_edifgbl.orientation),
3953 io_edifgbl.current_cell);
3954 if (ni == NONODEINST)
3955 {
3956 ttyputerr(_("error, line #%d: could not create rectangle"),
3957 io_edifgbl.lineno);
3958 io_edifgbl.errors++;
3959 }
3960 }
3961 io_edfreeptlist();
3962 break;
3963 case KRECTANGLE:
3964 if (kstack_ptr > 1 && (kstack[kstack_ptr-1] == KPAGESIZE ||
3965 kstack[kstack_ptr-1] == KBOUNDINGBOX)) break;
3966 if (io_edifgbl.pt_count == 2)
3967 {
3968 /* create the node instance */
3969 if (io_edifgbl.points->x > io_edifgbl.lastpt->x)
3970 {
3971 lx = io_edifgbl.lastpt->x;
3972 hx = io_edifgbl.points->x;
3973 } else
3974 {
3975 hx = io_edifgbl.lastpt->x;
3976 lx = io_edifgbl.points->x;
3977 }
3978 if (io_edifgbl.points->y > io_edifgbl.lastpt->y)
3979 {
3980 ly = io_edifgbl.lastpt->y;
3981 hy = io_edifgbl.points->y;
3982 } else
3983 {
3984 hy = io_edifgbl.lastpt->y;
3985 ly = io_edifgbl.points->y;
3986 }
3987 ni = newnodeinst(io_edifgbl.figure_group != NONODEPROTO ?
3988 io_edifgbl.figure_group : art_boxprim,
3989 lx, hx, ly, hy,
3990 io_edgettrans(io_edifgbl.orientation),
3991 io_edgetrot(io_edifgbl.orientation),
3992 io_edifgbl.current_cell);
3993 if (ni == NONODEINST)
3994 {
3995 ttyputerr(_("error, line #%d: could not create rectangle"),
3996 io_edifgbl.lineno);
3997 io_edifgbl.errors++;
3998 }
3999 else if (io_edifgbl.figure_group == art_openeddottedpolygonprim)
4000 {
4001 cnt = 5;
4002 cx = (io_edifgbl.points->x + io_edifgbl.lastpt->x) / 2;
4003 cy = (io_edifgbl.points->y + io_edifgbl.lastpt->y) / 2;
4004 pts[0] = io_edifgbl.points->x-cx;
4005 pts[1] = io_edifgbl.points->y-cy;
4006 pts[2] = io_edifgbl.points->x-cx;
4007 pts[3] = io_edifgbl.lastpt->y-cy;
4008 pts[4] = io_edifgbl.lastpt->x-cx;
4009 pts[5] = io_edifgbl.lastpt->y-cy;
4010 pts[6] = io_edifgbl.lastpt->x-cx;
4011 pts[7] = io_edifgbl.points->y-cy;
4012 pts[8] = io_edifgbl.points->x-cx;
4013 pts[9] = io_edifgbl.points->y-cy;
4014
4015 /* store the trace information */
4016 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)pts,
4017 VINTEGER|VISARRAY|((cnt*2)<<VLENGTHSH));
4018 }
4019 else if (io_edifgbl.geometry == GPIN)
4020 {
4021 /* create a rectangle using the pin-proto, and create the port
4022 * and export
4023 */
4024 /* ensure full sized port */
4025 lx += io_edifgbl.proto->lowx;
4026 hx += io_edifgbl.proto->highx;
4027 ly += io_edifgbl.proto->lowy;
4028 hy += io_edifgbl.proto->highy;
4029
4030 /* create the node instance */
4031 ni = io_edifiplacepin(io_edifgbl.proto, lx, hx, ly, hy,
4032 io_edgettrans(io_edifgbl.orientation),
4033 io_edgetrot(io_edifgbl.orientation),
4034 io_edifgbl.current_cell);
4035 if (ni == NONODEINST)
4036 {
4037 ttyputerr(_("error, line #%d: could not create pin"),
4038 io_edifgbl.lineno);
4039 io_edifgbl.errors++;
4040 }
4041 ppt = getportproto(ni->parent, io_edifgbl.name);
4042 if (ppt == NOPORTPROTO)
4043 ppt = newportproto(ni->parent, ni, default_iconport, io_edifgbl.name);
4044 if (ppt == NOPORTPROTO)
4045 {
4046 ttyputerr(_("error, line #%d: could not create port <%s>"),
4047 io_edifgbl.lineno, io_edifgbl.name);
4048 io_edifgbl.errors++;
4049 }
4050 }
4051 }
4052 io_edfreeptlist();
4053
4054 break;
4055
4056 case KARC:
4057 /* set array values */
4058 for (point = io_edifgbl.points, i = 0; point && i < 3; point = point->nextpt,i++)
4059 {
4060 x[i] = point->x;
4061 y[i] = point->y;
4062 }
4063 io_ededif_arc(x, y, &cx, &cy, &radius, &so, &ar, &j, &trans);
4064 lx = cx - radius; hx = cx + radius;
4065 ly = cy - radius; hy = cy + radius;
4066
4067 /* get the bounds of the circle */
4068 ni = newnodeinst(io_edifgbl.figure_group != NONODEPROTO &&
4069 io_edifgbl.figure_group != art_boxprim ?
4070 io_edifgbl.figure_group : art_circleprim, lx, hx, ly, hy,
4071 trans, j, io_edifgbl.current_cell);
4072 if (ni == NONODEINST)
4073 {
4074 ttyputerr(_("error, line #%d: could not create arc"), io_edifgbl.lineno);
4075 io_edifgbl.errors++;
4076 } else
4077 {
4078 /* store the angle of the arc */
4079 setarcdegrees(ni, so, ar*EPI/1800.0);
4080 }
4081 io_edfreeptlist();
4082 break;
4083
4084 case KSYMBOL:
4085 case KPAGE:
4086 np = io_edifgbl.current_cell;
4087 if (np != NONODEPROTO)
4088 {
4089 /* now compute the bounds of this cell */
4090 db_boundcell(np, &np->lowx, &np->highx, &np->lowy, &np->highy);
4091 }
4092 io_edifgbl.active_view = VNULL;
4093 break;
4094
4095 case KOPENSHAPE:
4096 case KPOLYGON:
4097 dopoly:
4098 if (io_edifgbl.pt_count == 0) break;
4099
4100 /* get the bounds of the poly */
4101 lx = hx = io_edifgbl.points->x;
4102 ly = hy = io_edifgbl.points->y;
4103 point = io_edifgbl.points->nextpt;
4104 while (point)
4105 {
4106 if (lx > point->x) lx = point->x;
4107 if (hx < point->x) hx = point->x;
4108 if (ly > point->y) ly = point->y;
4109 if (hy < point->y) hy = point->y;
4110 point = point->nextpt;
4111 }
4112 if (lx != hx || ly != hy)
4113 {
4114 if (io_edifgbl.figure_group != NONODEPROTO && io_edifgbl.figure_group != art_boxprim)
4115 np = io_edifgbl.figure_group; else
4116 {
4117 if (io_edifgbl.state == KPOLYGON) np = art_closedpolygonprim; else
4118 np = art_openedpolygonprim;
4119 }
4120 ni = newnodeinst(np, lx, hx, ly, hy, io_edgettrans(io_edifgbl.orientation),
4121 io_edgetrot(io_edifgbl.orientation), io_edifgbl.current_cell);
4122 if (ni == NONODEINST)
4123 {
4124 ttyputerr(_("error, line #%d: could not create polygon"), io_edifgbl.lineno);
4125 io_edifgbl.errors++;
4126 } else
4127 {
4128 pt = trace = emalloc((io_edifgbl.pt_count*2*SIZEOFINTBIG), el_tempcluster);
4129 if (trace == 0) RET_NOMEMORY();
4130 cx = (hx + lx) / 2;
4131 cy = (hy + ly) / 2;
4132 point = io_edifgbl.points;
4133 while (point != NOEPT)
4134 {
4135 *pt++ = point->x - cx;
4136 *pt++ = point->y - cy;
4137 point = point->nextpt;
4138 }
4139
4140 /* store the trace information */
4141 (void)setvalkey((INTBIG)ni, VNODEINST, el_trace_key, (INTBIG)trace,
4142 VINTEGER|VISARRAY|((io_edifgbl.pt_count*2)<<VLENGTHSH));
4143
4144 /* free the polygon memory */
4145 efree((CHAR *)trace);
4146 }
4147 }
4148 io_edfreeptlist();
4149 break;
4150 case KARRAY:
4151 switch (kstack[kstack_ptr-1])
4152 {
4153 case KPORT:
4154 io_edmake_electric_name(io_edifgbl.port_reference, io_edifgbl.port_name, io_edifgbl.arrayx,
4155 io_edifgbl.arrayy);
4156 default:
4157 break;
4158 }
4159 if (io_edifgbl.arrayx == 0) io_edifgbl.arrayx = 1;
4160 if (io_edifgbl.arrayy == 0) io_edifgbl.arrayy = 1;
4161 break;
4162 case KMEMBER:
4163 if (io_edifgbl.memberx != -1)
4164 {
4165 /* adjust the name of the current INSTANCE/NET/PORT(/VALUE) */
4166 if (io_edifgbl.membery != -1)
4167 (void)esnprintf(basename, WORD+1, x_("[%d,%d]"), io_edifgbl.memberx, io_edifgbl.membery);
4168 else (void)esnprintf(basename, WORD+1, x_("[%d]"), io_edifgbl.memberx);
4169 switch (kstack[kstack_ptr-1])
4170 {
4171 case KINSTANCEREF:
4172 (void)estrcat(io_edifgbl.instance_reference, basename);
4173 break;
4174 case KPORTREF:
4175 (void)estrcat(io_edifgbl.port_reference, basename);
4176 break;
4177 default:
4178 break;
4179 }
4180 }
4181 break;
4182 case KDESIGN:
4183 if (io_edifgbl.proto != NONODEPROTO)
4184 {
4185 if (io_verbose < 0)
4186 {
4187 infstr = initinfstr();
4188 formatinfstr(infstr, _("Design %s"),
4189 io_edifgbl.proto->protoname);
4190 DiaSetTextProgress(io_edifprogressdialog, returninfstr(infstr));
4191 }
4192 else ttyputmsg(_("Design %s"), io_edifgbl.proto->protoname);
4193 io_edifgbl.library->curnodeproto = io_edifgbl.proto;
4194 }
4195 break;
4196
4197 case KEDIF:
4198 /* free the port freelist */
4199 for (eport = io_edifgbl.free_ports; eport != NOEDPORT; eport = neport)
4200 {
4201 neport = eport->next;
4202 efree((CHAR *)eport);
4203 }
4204 io_edifgbl.free_ports = NOEDPORT;
4205
4206 /* free the netport list */
4207 io_edfreenetports();
4208 break;
4209 default:
4210 break;
4211 }
4212 }
4213 if (kstack_ptr) io_edifgbl.state = kstack[--kstack_ptr]; else
4214 io_edifgbl.state = KINIT;
4215 return(0);
4216 }
4217 else return(1);
4218 }
4219
4220 /* module: io_edprocess_integer
4221 function: will do cleanup processing of an integer argument such as in (array (...) 1 2)
4222 */
4223 void io_edprocess_integer(INTBIG value)
4224 {
4225 if (kstack_ptr)
4226 {
4227 if (!io_edifgbl.ignoreblock)
4228 {
4229 switch (io_edifgbl.state)
4230 {
4231 case KARRAY:
4232 if (io_edifgbl.arrayx == 0) io_edifgbl.arrayx = value;
4233 else if (io_edifgbl.arrayy == 0) io_edifgbl.arrayy = value;
4234 break;
4235 case KMEMBER:
4236 if (io_edifgbl.memberx == -1) io_edifgbl.memberx = value;
4237 else if (io_edifgbl.membery == -1) io_edifgbl.membery = value;
4238 break;
4239 default:
4240 break;
4241 }
4242 }
4243 }
4244 }
4245
4246 INTSML io_edgetrot(OTYPES orientation)
4247 {
4248 switch (orientation)
4249 {
4250 case OR0: return(0);
4251 case OR90: return(90*10);
4252 case OR180: return(180*10);
4253 case OR270: return(270*10);
4254 case OMX: return(270*10);
4255 case OMY: return(90*10);
4256 case OMXR90: return(180*10);
4257 case OMYR90: return(0);
4258 default: break;
4259 }
4260 return(0);
4261 }
4262
4263 INTSML io_edgettrans(OTYPES orientation)
4264 {
4265 switch (orientation)
4266 {
4267 case OR0: return(0);
4268 case OR90: return(0);
4269 case OR180: return(0);
4270 case OR270: return(0);
4271 case OMY: return(1);
4272 case OMX: return(1);
4273 case OMYR90: return(1);
4274 case OMXR90: return(1);
4275 default: break;
4276 }
4277 return(0);
4278 }
4279
4280 /*
4281 * Routine to return the text height to use when it says "textheight" units in the EDIF file.
4282 */
4283 INTBIG io_ediftextsize(INTBIG textheight)
4284 {
4285 REGISTER INTBIG i, lambda;
4286
4287 lambda = el_curlib->lambda[io_edifgbl.technology->techindex];
4288 i = io_edifgbl.textheight / lambda;
4289 if (i < 0) i = 4;
4290 if (i > TXTMAXQLAMBDA) i = TXTMAXQLAMBDA;
4291 i = TXTSETQLAMBDA(i);
4292 return(i);
4293 }
4294
4295 /* helper routine for "esort" */
4296 int io_edcompare_name(const void *name1, const void *name2)
4297 {
4298 REGISTER NAMETABLE_PTR *n1, *n2;
4299
4300 n1 = (NAMETABLE_PTR *)name1;
4301 n2 = (NAMETABLE_PTR *)name2;
4302 return(namesame((*n1)->original, (*n2)->original));
4303 }
4304
4305 /* Will check if a string is an valid integer */
4306 INTBIG io_edis_integer(CHAR *buffer)
4307 {
4308 /* remove sign */
4309 if (*buffer == '+' || *buffer == '-') buffer++;
4310 while (isdigit(*buffer))
4311 {
4312 buffer++;
4313 if (*buffer == 0) return(1);
4314 }
4315 return(0);
4316 }
4317
4318 /* get a keyword routine */
4319 CHAR *io_edget_keyword(CHAR *buffer)
4320 {
4321 CHAR *p;
4322
4323 /* look for a '(' before the edif keyword */
4324 while ((p = io_edget_token(buffer, 0)) && (*p != '('))
4325 {
4326 if (*p == ')') io_edpop_stack(); else
4327 if (io_edis_integer(buffer)) io_edprocess_integer(eatoi(buffer));
4328 }
4329 return(io_edget_token(buffer, 0));
4330 }
4331
4332 /* get a token routine */
4333 CHAR *io_edget_token(CHAR *buffer, CHAR idelim)
4334 {
4335 CHAR *sptr;
4336 CHAR delim;
4337
4338 /* locate the first non-white space character for non-delimited searches */
4339 delim = idelim;
4340 if (!delim)
4341 {
4342 if (io_edpos_token() == NULL)
4343 return(NULL);
4344 }
4345
4346 /* set up the string copy */
4347 sptr = buffer;
4348 if (!delim && *io_edifgbl.pos == '"')
4349 {
4350 /* string search */
4351 delim = '"';
4352 *(sptr++) = *(io_edifgbl.pos++);
4353 }
4354
4355 /* non locate the next white space or the delimiter */
4356 for(;;)
4357 {
4358 if (*io_edifgbl.pos == 0)
4359 {
4360 /* end of string, get the next line */
4361 if (!io_edget_line(io_edifgbl.buffer, LINE, io_edifgbl.edif_file))
4362 {
4363 /* end-of-file, if no delimiter return NULL, otherwise the string */
4364 if (delim) break;
4365 *sptr = 0;
4366 return(buffer);
4367 }
4368 io_edifgbl.pos = io_edifgbl.buffer;
4369 } else if (!delim)
4370 {
4371 switch (*io_edifgbl.pos)
4372 {
4373 /* the space characters */
4374 case '\n':
4375 case '\r':
4376 io_edifgbl.lineno++;
4377 /* FALLTHROUGH */
4378 case ' ':
4379 case '\t':
4380 *sptr = 0;
4381 /* skip to the next character */
4382 io_edifgbl.pos++;
4383 return(buffer);
4384 /* special EDIF delimiters */
4385 case '(':
4386 case ')':
4387 if (sptr == buffer)
4388 *(sptr++) = *(io_edifgbl.pos++);
4389 *sptr = 0;
4390 return(buffer);
4391 default:
4392 *(sptr++) = *(io_edifgbl.pos++);
4393 break;
4394 }
4395 } else
4396 {
4397 /* check for user specified delimiter */
4398 if (*io_edifgbl.pos == delim)
4399 {
4400 /* skip the delimiter, unless string */
4401 if (delim != idelim) *(sptr++) = *(io_edifgbl.pos++); else
4402 io_edifgbl.pos++;
4403 *sptr = 0;
4404 return(buffer);
4405 } else
4406 {
4407 if (*io_edifgbl.pos == '\r' || *io_edifgbl.pos == '\n')
4408 {
4409 io_edifgbl.lineno++;
4410 }
4411
4412 *(sptr++) = *(io_edifgbl.pos++);
4413 }
4414 }
4415 }
4416 return(NULL);
4417 }
4418
4419 /*
4420 * Module: io_edpos_token
4421 * Function: special routine to position to the next token
4422 */
4423 CHAR *io_edpos_token(void)
4424 {
4425 for(;;)
4426 {
4427 switch (*io_edifgbl.pos)
4428 {
4429 case 0:
4430 /* end of string, get the next line */
4431 if (!io_edget_line(io_edifgbl.buffer, LINE, io_edifgbl.edif_file))
4432 {
4433 /* end-of-file */
4434 return(NULL);
4435 }
4436 io_edifgbl.pos = io_edifgbl.buffer;
4437 break;
4438
4439 /* the space characters */
4440 case '\n':
4441 case '\r':
4442 io_edifgbl.lineno++;
4443 /* FALLTHROUGH */
4444 case ' ':
4445 case '\t':
4446 io_edifgbl.pos++;
4447 break;
4448 default:
4449 return(io_edifgbl.pos);
4450 }
4451 }
4452 }
4453
4454 /*
4455 * routine to read a line from file "file" and place it in "line" (which has
4456 * up to "limit" characters). Returns FALSE on end-of-file. Updates "filepos".
4457 */
4458 BOOLEAN io_edget_line(CHAR *line, INTBIG limit, FILE *file)
4459 {
4460 REGISTER CHAR *pp;
4461 REGISTER INTSML c;
4462 REGISTER INTBIG total;
4463
4464 pp = line;
4465 total = 1;
4466 for(;;)
4467 {
4468 c = xgetc(file);
4469 if (c == EOF)
4470 {
4471 if (pp == line) return(FALSE);
4472 break;
4473 }
4474 filepos++;
4475 *pp = (CHAR)c;
4476 if (*pp == '\n')
4477 {
4478 pp++;
4479 break;
4480 }
4481 pp++;
4482 if ((++total) >= limit) break;
4483 }
4484 *pp = 0;
4485 return(TRUE);
4486 }
4487
4488 /* get a delimeter routine */
4489 void io_edget_delim(CHAR delim)
4490 {
4491 CHAR *token;
4492
4493 token = io_edpos_token();
4494 if (token == NULL) longjmp(io_edifgbl.env, LONGJMPEOF);
4495 if (*token != delim) longjmp(io_edifgbl.env, LONGJMPILLDELIM); else
4496 io_edifgbl.pos++;
4497 }
4498
4499 /************ INPUT SUPPORT *********/
4500
4501 /* This function allocates ports */
4502 INTBIG io_edallocport(void)
4503 {
4504 EDPORT_PTR port;
4505
4506 if (io_edifgbl.free_ports != NOEDPORT)
4507 {
4508 port = io_edifgbl.free_ports;
4509 io_edifgbl.free_ports = port->next;
4510 } else
4511 {
4512 port = (EDPORT_PTR)emalloc(sizeof (EDPORT), io_tool->cluster);
4513 if (port == NOEDPORT) RET_NOMEMORY();
4514 }
4515
4516 port->next = io_edifgbl.ports;
4517 io_edifgbl.ports = port;
4518 if (allocstring(&port->reference, io_edifgbl.port_reference, io_tool->cluster))
4519 RET_NOMEMORY();
4520 if (allocstring(&port->name, io_edifgbl.port_name, io_tool->cluster))
4521 RET_NOMEMORY();
4522
4523 port->direction = io_edifgbl.direction;
4524 port->arrayx = io_edifgbl.arrayx;
4525 port->arrayy = io_edifgbl.arrayy;
4526 return(0);
4527 }
4528
4529 INTBIG io_edallocproperty(CHAR *name, PROPERTY_TYPE type, int integer,
4530 float number, CHAR *string)
4531 {
4532 EDPROPERTY_PTR property;
4533 REGISTER void *infstr;
4534
4535 if (io_edifgbl.free_properties != NOEDPROPERTY)
4536 {
4537 property = io_edifgbl.free_properties;
4538 io_edifgbl.free_properties = property->next;
4539 } else
4540 {
4541 property = (EDPROPERTY_PTR)emalloc(sizeof (EDPROPERTY), io_tool->cluster);
4542 if (property == NOEDPROPERTY)
4543 RET_NOMEMORY();
4544 }
4545
4546 property->next = io_edifgbl.properties;
4547 io_edifgbl.properties = property;
4548 infstr = initinfstr();
4549 formatinfstr(infstr, x_("ATTR_%s"), name);
4550 if (allocstring(&property->name, returninfstr(infstr), io_tool->cluster))
4551 RET_NOMEMORY();
4552 property->type = type;
4553 switch (property->type)
4554 {
4555 case PINTEGER:
4556 property->val.integer = integer;
4557 break;
4558 case PNUMBER:
4559 property->val.number = number;
4560 break;
4561 case PSTRING:
4562 if (allocstring(&property->val.string, string, io_tool->cluster))
4563 RET_NOMEMORY();
4564 break;
4565 default:
4566 break;
4567 }
4568 return(0);
4569 }
4570
4571 /* This function allocates net ports */
4572 INTBIG io_edallocnetport(void)
4573 {
4574 EDNETPORT_PTR netport;
4575
4576 if (io_edifgbl.free_netports != NOEDNETPORT)
4577 {
4578 netport = io_edifgbl.free_netports;
4579 io_edifgbl.free_netports = netport->next;
4580 } else
4581 {
4582 netport = (EDNETPORT_PTR)emalloc(sizeof (EDNETPORT), io_tool->cluster);
4583 if (netport == NOEDNETPORT) RET_NOMEMORY();
4584 }
4585
4586 if (io_edifgbl.firstnetport == NOEDNETPORT)io_edifgbl.firstnetport = netport; else
4587 io_edifgbl.lastnetport->next = netport;
4588
4589 io_edifgbl.lastnetport = netport;
4590 netport->next = NOEDNETPORT;
4591 netport->ni = NONODEINST;
4592 netport->pp = NOPORTPROTO;
4593 netport->member = 0;
4594 return(0);
4595 }
4596
4597 /* free the netport list */
4598 void io_edfreenetports(void)
4599 {
4600 EDNETPORT_PTR nport;
4601
4602 while (io_edifgbl.firstnetport != NOEDNETPORT)
4603 {
4604 nport = io_edifgbl.firstnetport;
4605 io_edifgbl.firstnetport = nport->next;
4606 nport->next = io_edifgbl.free_netports;
4607 io_edifgbl.free_netports = nport;
4608 }
4609 io_edifgbl.firstnetport = io_edifgbl.lastnetport = NOEDNETPORT;
4610 }
4611
4612 /*
4613 * Module: io_edeq_of_a_line
4614 * Function: Calculates the equation of a line (Ax + By + C = 0)
4615 * Inputs: sx, sy - Start point
4616 * ex, ey - End point
4617 * px, py - Point line should pass through
4618 * Outputs: A, B, C - constants for the line
4619 */
4620 void io_edeq_of_a_line(double sx, double sy, double ex, double ey, double *A, double *B, double *C)
4621 {
4622 if (sx == ex)
4623 {
4624 *A = 1.0;
4625 *B = 0.0;
4626 *C = -ex;
4627 } else if (sy == ey)
4628 {
4629 *A = 0.0;
4630 *B = 1.0;
4631 *C = -ey;
4632 } else
4633 {
4634 /* let B = 1 then */
4635 *B = 1.0;
4636 if (sx != 0.0)
4637 {
4638 /* Ax1 + y1 + C = 0 => A = -(C + y1) / x1 */
4639 /* C = -Ax2 - y2 => C = (Cx2 + y1x2) / x1 - y2 => Cx1 - Cx2 = y1x2 - y2x1 */
4640 /* C = (y2x1 - y1x2) / (x2 - x1) */
4641 *C = (ey * sx - sy * ex) / (ex - sx);
4642 *A = -(*C + sy) / sx;
4643 } else
4644 {
4645 *C = (sy * ex - ey * sx) / (sx - ex);
4646 *A = -(*C + ey) / ex;
4647 }
4648 }
4649 }
4650
4651 /*
4652 * Module: io_eddetermine_intersection
4653 * Function: Will determine the intersection of two lines
4654 * Inputs: Ax + By + C = 0 form
4655 * Outputs: x, y - the point of intersection
4656 * returns 1 if found, 0 if non-intersecting
4657 */
4658 INTBIG io_eddetermine_intersection(double A[2], double B[2], double C[2], double *x, double *y)
4659 {
4660 double A1B2, A2B1;
4661 double A2C1, A1C2;
4662 double X, Y;
4663
4664 /* check for parallel lines */
4665 if ((A1B2 = A[0] * B[1]) == (A2B1 = A[1] * B[0]))
4666 {
4667 /* check for coincident lines */
4668 if (C[0] == C[1]) return(-1);
4669 return(0);
4670 }
4671 A1C2 = A[0] * C[1];
4672 A2C1 = A[1] * C[0];
4673
4674 if (A[0])
4675 {
4676 Y = (A2C1 - A1C2) / (A1B2 - A2B1);
4677 X = -(B[0] * Y + C[0]) / A[0];
4678 } else
4679 {
4680 Y = (A1C2 - A2C1) / (A2B1 - A1B2);
4681 X = -(B[1] * Y + C[1]) / A[1];
4682 }
4683 *y = Y;
4684 *x = X;
4685 return(1);
4686 }
4687
4688 void io_ededif_arc(INTBIG ix[3], INTBIG iy[3], INTBIG *ixc, INTBIG *iyc, INTBIG *r, double *so,
4689 double *ar, INTBIG *rot, INTBIG *trans)
4690 {
4691 double x[3], y[3], px[3], py[3], a[3];
4692 double A[2], B[2], C[2];
4693 double dx, dy, R, area, xc, yc;
4694 INTBIG i;
4695
4696 for(i=0; i<3; i++)
4697 {
4698 x[i] = (double)ix[i];
4699 y[i] = (double)iy[i];
4700 }
4701
4702 /* get line equations of perpendicular bi-sectors of p1 to p2 */
4703 px[1] = (x[0] + x[1]) / 2.0;
4704 py[1] = (y[0] + y[1]) / 2.0;
4705
4706 /* now rotate end point 90 degrees */
4707 px[0] = px[1] - (y[0] - py[1]);
4708 py[0] = py[1] + (x[0] - px[1]);
4709 io_edeq_of_a_line(px[0], py[0], px[1], py[1], &A[0], &B[0], &C[0]);
4710
4711 /* get line equations of perpendicular bi-sectors of p2 to p3 */
4712 px[1] = (x[2] + x[1]) / 2.0;
4713 py[1] = (y[2] + y[1]) / 2.0;
4714
4715 /* now rotate end point 90 degrees */
4716 px[2] = px[1] - (y[2] - py[1]);
4717 py[2] = py[1] + (x[2] - px[1]);
4718 io_edeq_of_a_line(px[1], py[1], px[2], py[2], &A[1], &B[1], &C[1]);
4719
4720 /* determine the point of intersection */
4721 (void)io_eddetermine_intersection(A, B, C, &xc, &yc);
4722
4723 *ixc = rounddouble(xc);
4724 *iyc = rounddouble(yc);
4725
4726 dx = ((double)*ixc) - x[0];
4727 dy = ((double)*iyc) - y[0];
4728 R = sqrt(dx * dx + dy * dy);
4729 *r = rounddouble(R);
4730
4731 /* now calculate the angle to the start and endpoint */
4732 dx = x[0] - xc; dy = y[0] - yc;
4733 if (dx == 0.0 && dy == 0.0)
4734 {
4735 ttyputerr(_("Domain error doing arc computation"));
4736 return;
4737 }
4738 a[0] = atan2(dy, dx) * 1800.0 / EPI;
4739 if (a[0] < 0.0) a[0] += 3600.0;
4740
4741 dx = x[2] - xc; dy = y[2] - yc;
4742 if (dx == 0.0 && dy == 0.0)
4743 {
4744 ttyputerr(_("Domain error doing arc computation"));
4745 return;
4746 }
4747 a[2] = atan2(dy, dx) * 1800.0 / EPI;
4748 if (a[2] < 0.0) a[2] += 3600.0;
4749
4750 /* determine the angle of rotation and object orientation */
4751 /* determine the direction */
4752 /* calculate x1*y2 + x2*y3 + x3*y1 - y1*x2 - y2*x3 - y3*x1 */
4753 area = x[0]*y[1] + x[1]*y[2] + x[2]*y[0] - y[0]*x[1] - y[1]*x[2] - y[2]*x[0];
4754 if (area > 0.0)
4755 {
4756 /* counter clockwise */
4757 if (a[2] < a[0]) a[2] += 3600.0;
4758 *ar = a[2] - a[0];
4759 *rot = rounddouble(a[0]);
4760 *so = (a[0] - (double)*rot) * EPI / 1800.0;
4761 *trans = 0;
4762 } else
4763 {
4764 /* clockwise */
4765 if (a[0] > 2700)
4766 {
4767 *rot = 3600 - rounddouble(a[0]) + 2700;
4768 *so = ((3600.0 - a[0] + 2700.0) - (double)*rot) * EPI / 1800.0;
4769 } else
4770 {
4771 *rot = 2700 - rounddouble(a[0]);
4772 *so = ((2700.0 - a[0]) - (double)*rot) * EPI / 1800.0;
4773 }
4774 if (a[0] < a[2]) a[0] += 3600;
4775 *ar = a[0] - a[2];
4776 *trans = 1;
4777 }
4778 }
4779
4780 /*
4781 * routine to generate an icon in library "lib" with name "iconname" from the
4782 * port list in "fpp". The icon cell is called "pt". The icon cell is
4783 * returned (NONODEPROTO on error). (Note: copied and adapted from us_makeiconcell)
4784 */
4785 NODEPROTO *io_edmakeiconcell(PORTPROTO *fpp, CHAR *iconname, CHAR *pt, LIBRARY *lib)
4786 {
4787 REGISTER NODEPROTO *np, *bbproto, *pinproto, *buspproto, *pintype;
4788 REGISTER NODEINST *bbni, *pinni;
4789 REGISTER PORTPROTO *pp, *port, *inputport, *outputport, *bidirport,
4790 *topport, *whichport, *bpp;
4791 REGISTER ARCPROTO *wireproto, *busproto, *wiretype;
4792 REGISTER INTBIG inputside, outputside, bidirside, topside;
4793 REGISTER INTBIG eindex, xsize, ysize, xpos, ypos, xbbpos, ybbpos, spacing,
4794 lambda;
4795 REGISTER UINTBIG character;
4796 REGISTER VARIABLE *var;
4797
4798 /* get the necessary symbols */
4799 pinproto = sch_wirepinprim;
4800 buspproto = sch_buspinprim;
4801 bbproto = sch_bboxprim;
4802 wireproto = sch_wirearc;
4803 busproto = sch_busarc;
4804 outputport = bbproto->firstportproto;
4805 topport = outputport->nextportproto;
4806 inputport = topport->nextportproto;
4807 bidirport = inputport->nextportproto;
4808
4809 /* create the new icon cell */
4810 lambda = lib->lambda[sch_tech->techindex];
4811 np = us_newnodeproto(pt, lib);
4812 if (np == NONODEPROTO)
4813 {
4814 ttyputerr(_("Cannot create icon %s"), pt);
4815 return(NONODEPROTO);
4816 }
4817 np->userbits |= WANTNEXPAND;
4818
4819 /* determine number of inputs and outputs */
4820 inputside = outputside = bidirside = topside = 0;
4821 for(pp = fpp; pp != NOPORTPROTO; pp = pp->nextportproto)
4822 {
4823 if ((pp->userbits&BODYONLY) != 0) continue;
4824 character = pp->userbits & STATEBITS;
4825
4826 /* special detection for power and ground ports */
4827 if (portispower(pp) || portisground(pp)) character = GNDPORT;
4828
4829 /* make a count of the types of ports and save it on the ports */
4830 switch (character)
4831 {
4832 case OUTPORT:
4833 pp->temp1 = outputside++;
4834 break;
4835 case BIDIRPORT:
4836 pp->temp1 = bidirside++;
4837 break;
4838 case PWRPORT:
4839 case GNDPORT:
4840 pp->temp1 = topside++;
4841 break;
4842 default: /* INPORT, unlabeled, and all CLOCK ports */
4843 pp->temp1 = inputside++;
4844 break;
4845 }
4846 }
4847
4848 /* create the Black Box with the correct size */
4849 ysize = maxi(maxi(inputside, outputside), 5) * 2 * lambda;
4850 xsize = maxi(maxi(topside, bidirside), 3) * 2 * lambda;
4851
4852 /* create the Black Box instance */
4853 bbni = newnodeinst(bbproto, 0, xsize, 0, ysize, 0, 0, np);
4854 if (bbni == NONODEINST) return(NONODEPROTO);
4855
4856 /* put the original cell name on the Black Box */
4857 var = setval((INTBIG)bbni, VNODEINST, x_("SCHEM_function"), (INTBIG)iconname, VSTRING|VDISPLAY);
4858 if (var != NOVARIABLE) defaulttextdescript(var->textdescript, bbni->geom);
4859
4860 /* place pins around the Black Box */
4861 for(pp = fpp; pp != NOPORTPROTO; pp = pp->nextportproto)
4862 {
4863 if ((pp->userbits&BODYONLY) != 0) continue;
4864 character = pp->userbits & STATEBITS;
4865
4866 /* special detection for power and ground ports */
4867 if (portispower(pp) || portisground(pp)) character = GNDPORT;
4868
4869 /* make a count of the types of ports and save it on the ports */
4870 switch (character)
4871 {
4872 case OUTPORT:
4873 xpos = xsize + 2 * lambda;
4874 xbbpos = xsize;
4875 eindex = pp->temp1;
4876 spacing = 2 * lambda;
4877 if (outputside*2 < inputside) spacing = 4 * lambda;
4878 ybbpos = ypos = ysize - ((ysize - (outputside-1)*spacing) / 2 + eindex * spacing);
4879 whichport = outputport;
4880 break;
4881 case BIDIRPORT:
4882 eindex = pp->temp1;
4883 spacing = 2 * lambda;
4884 if (bidirside*2 < topside) spacing = 4 * lambda;
4885 xbbpos = xpos = xsize - ((xsize - (bidirside-1)*spacing) / 2 + eindex * spacing);
4886 ypos = -2 * lambda;
4887 ybbpos = 0;
4888 whichport = bidirport;
4889 break;
4890 case PWRPORT:
4891 case GNDPORT:
4892 eindex = pp->temp1;
4893 spacing = 2 * lambda;
4894 if (topside*2 < bidirside) spacing = 4 * lambda;
4895 xbbpos = xpos = xsize - ((xsize - (topside-1)*spacing) / 2 + eindex * spacing);
4896 ypos = ysize + 2 * lambda;
4897 ybbpos = ysize;
4898 whichport = topport;
4899 break;
4900 default: /* INPORT, unlabeled, and all CLOCK ports */
4901 xpos = -2 * lambda;
4902 xbbpos = 0;
4903 eindex = pp->temp1;
4904 spacing = 2 * lambda;
4905 if (inputside*2 < outputside) spacing = 4 * lambda;
4906 ybbpos = ypos = ysize - ((ysize - (inputside-1)*spacing) / 2 + eindex * spacing);
4907 whichport = inputport;
4908 break;
4909 }
4910
4911 /* determine type of pin */
4912 pintype = pinproto;
4913 wiretype = wireproto;
4914 if (pp->subnodeinst != NONODEINST)
4915 {
4916 bpp = pp;
4917 while (bpp->subnodeinst->proto->primindex == 0) bpp = bpp->subportproto;
4918 if (bpp->subnodeinst->proto == buspproto)
4919 {
4920 pintype = buspproto;
4921 wiretype = busproto;
4922 }
4923 }
4924
4925 /* create the pin */
4926 pinni = io_edifiplacepin(pintype, xpos, xpos, ypos, ypos, 0, 0, np);
4927 if (pinni == NONODEINST) return(NONODEPROTO);
4928
4929 /* export the port that should be on this pin */
4930 port = newportproto(np, pinni, pintype->firstportproto, pp->protoname);
4931 if (port != NOPORTPROTO)
4932 port->userbits = pp->userbits | PORTDRAWN;
4933
4934 /* wire this pin to the black box */
4935 (void)newarcinst(wiretype, defaultarcwidth(wiretype),
4936 us_makearcuserbits(wiretype), pinni, pintype->firstportproto,
4937 xpos, ypos, bbni, whichport, xbbpos, ybbpos, np);
4938 }
4939 return(np);
4940 }
4941
4942 void io_ednamearc(ARCINST *ai)
4943 {
4944 int Ix, Iy;
4945 REGISTER VARIABLE *var;
4946 CHAR *name, basename[WORD+1] ;
4947
4948 if (io_edifgbl.isarray)
4949 {
4950 /* name the bus */
4951 if (io_edifgbl.net_reference)
4952 {
4953 (void)setvalkey((INTBIG)ai, VARCINST, EDIF_name_key,
4954 (INTBIG)io_edifgbl.net_reference, VSTRING);
4955 }
4956
4957 /* a typical foreign array bus will have some range value appended
4958 * to the name. This will cause some odd names with duplicate values
4959 */
4960 name = basename;
4961 *name = 0;
4962 for (Ix = 0; Ix < io_edifgbl.arrayx; Ix++)
4963 {
4964 for (Iy = 0; Iy < io_edifgbl.arrayy; Iy++)
4965 {
4966 if (name != basename) *name++ = ',';
4967 if (io_edifgbl.arrayx > 1)
4968 {
4969 if (io_edifgbl.arrayy > 1)
4970 (void)esnprintf(name, WORD, x_("%s[%d,%d]"), io_edifgbl.net_name, Ix, Iy);
4971 else
4972 (void)esnprintf(name, WORD, x_("%s[%d]"), io_edifgbl.net_name, Ix);
4973 }
4974 else (void)esnprintf(name, WORD, x_("%s[%d]"), io_edifgbl.net_name, Iy);
4975 name += estrlen(name);
4976 }
4977 }
4978 var = setvalkey((INTBIG)ai, VARCINST, el_arc_name_key, (INTBIG)basename, VSTRING);
4979 if (var != NOVARIABLE)
4980 defaulttextsize(4, var->textdescript);
4981 } else
4982 {
4983 if (io_edifgbl.net_reference)
4984 {
4985 (void)setvalkey((INTBIG)ai, VARCINST, EDIF_name_key,
4986 (INTBIG)io_edifgbl.net_reference, VSTRING);
4987 }
4988 if (io_edifgbl.net_name)
4989 {
4990 /* set name of arc but don't display name */
4991 var = setvalkey((INTBIG)ai, VARCINST, el_arc_name_key,
4992 (INTBIG)io_edifgbl.net_name, VSTRING);
4993 if (var != NOVARIABLE)
4994 defaulttextsize(4, var->textdescript);
4995 }
4996 }
4997 }
4998
4999 INTBIG io_edfindport(NODEPROTO *cell, INTBIG x, INTBIG y, ARCPROTO *ap, NODEINST *nis[],
5000 PORTPROTO *pps[])
5001 {
5002 INTBIG cnt;
5003 ARCINST *ai = NOARCINST, *ar1,*ar2;
5004 ARCPROTO *nap;
5005 NODEINST *ni, *fno, *tno;
5006 PORTPROTO *fpt, *tpt, *pp;
5007 NODEPROTO *np, *pnt;
5008 INTBIG wid, bits1, bits2, lx, hx, ly, hy, j;
5009 INTBIG fendx, fendy, tendx, tendy;
5010
5011 cnt = io_edfindport_geom(cell, x, y, ap, nis, pps, &ai);
5012
5013 if (cnt == 0 && ai != NOARCINST)
5014 {
5015 /* direct hit on an arc, verify connection */
5016 nap = ai->proto;
5017 np = getpinproto(nap);
5018 if (np == NONODEPROTO) return(0);
5019 pp = np->firstportproto;
5020 for (j = 0; pp->connects[j] != NOARCPROTO; j++)
5021 if (pp->connects[j] == ap) break;
5022 if (pp->connects[j] == NOARCPROTO) return(0);
5023
5024 /* try to split arc (from us_getnodeonarcinst)*/
5025 /* break is at (prefx, prefy): save information about the arcinst */
5026 fno = ai->end[0].nodeinst; fpt = ai->end[0].portarcinst->proto;
5027 tno = ai->end[1].nodeinst; tpt = ai->end[1].portarcinst->proto;
5028 fendx = ai->end[0].xpos; fendy = ai->end[0].ypos;
5029 tendx = ai->end[1].xpos; tendy = ai->end[1].ypos;
5030 wid = ai->width; pnt = ai->parent;
5031 bits1 = bits2 = ai->userbits;
5032 if ((bits1&ISNEGATED) != 0)
5033 {
5034 if ((bits1&REVERSEEND) == 0) bits2 &= ~ISNEGATED; else
5035 bits1 &= ~ISNEGATED;
5036 }
5037 if (figureangle(fendx,fendy, x,y) != figureangle(x,y, tendx, tendy))
5038 {
5039 bits1 &= ~FIXANG;
5040 bits2 &= ~FIXANG;
5041 }
5042
5043 /* create the splitting pin */
5044 lx = x - (np->highx-np->lowx)/2; hx = lx + np->highx-np->lowx;
5045 ly = y - (np->highy-np->lowy)/2; hy = ly + np->highy-np->lowy;
5046 ni = io_edifiplacepin(np, lx,hx, ly,hy, 0, 0, pnt);
5047 if (ni == NONODEINST)
5048 {
5049 ttyputerr(_("Cannot create splitting pin"));
5050 return(0);
5051 }
5052 endobjectchange((INTBIG)ni, VNODEINST);
5053
5054 /* set the node, and port */
5055 nis[cnt] = ni;
5056 pps[cnt++] = pp;
5057
5058 /* create the two new arcinsts */
5059 ar1 = newarcinst(nap, wid, bits1, fno, fpt, fendx, fendy, ni, pp, x, y, pnt);
5060 ar2 = newarcinst(nap, wid, bits2, ni, pp, x, y, tno, tpt, tendx, tendy, pnt);
5061 if (ar1 == NOARCINST || ar2 == NOARCINST)
5062 {
5063 ttyputerr(_("Error creating the split arc parts"));
5064 return(cnt);
5065 }
5066 (void)copyvars((INTBIG)ai, VARCINST, (INTBIG)ar1, VARCINST, FALSE);
5067 endobjectchange((INTBIG)ar1, VARCINST);
5068 endobjectchange((INTBIG)ar2, VARCINST);
5069
5070 /* delete the old arcinst */
5071 startobjectchange((INTBIG)ai, VARCINST);
5072 if (killarcinst(ai))
5073 ttyputerr(_("Error deleting original arc"));
5074 }
5075
5076 return(cnt);
5077 }
5078
5079 /* module: ro_mazefindport
5080 function: will locate the nodeinstance and portproto corresponding to
5081 to a direct intersection with the given point.
5082 inputs:
5083 cell - cell to search
5084 x, y - the point to exam
5085 ap - the arc used to connect port (must match pp)
5086 nis - pointer to ni pointer buffer.
5087 pps - pointer to portproto pointer buffer.
5088 outputs:
5089 returns cnt if found, 0 not found, -1 on error
5090 ni = found ni instance
5091 pp = found pp proto.
5092 */
5093 INTBIG io_edfindport_geom(NODEPROTO *cell, INTBIG x, INTBIG y, ARCPROTO *ap,
5094 NODEINST *nis[], PORTPROTO *pps[], ARCINST **ai)
5095 {
5096 REGISTER INTBIG j, cnt, sea, dist, bestdist, bestpx, bestpy, bits, wid,
5097 lx, hx, ly, hy, xs, ys;
5098 INTBIG px, py;
5099 REGISTER GEOM *geom;
5100 REGISTER ARCINST *newai;
5101 static POLYGON *poly = NOPOLYGON;
5102 REGISTER PORTPROTO *pp, *bestpp;
5103 REGISTER NODEINST *ni, *bestni;
5104 NODEPROTO *np;
5105
5106 (void)needstaticpolygon(&poly, 4, io_tool->cluster);
5107
5108 cnt = 0;
5109 bestni = NONODEINST;
5110 sea = initsearch(x, x, y, y, cell);
5111 for(;;)
5112 {
5113 geom = nextobject(sea);
5114 if (geom == NOGEOM) break;
5115
5116 switch (geom->entryisnode)
5117 {
5118 case TRUE:
5119 /* now locate a portproto */
5120 ni = geom->entryaddr.ni;
5121 for (pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
5122 {
5123 shapeportpoly(ni, pp, poly, FALSE);
5124 if (isinside(x, y, poly))
5125 {
5126 /* check if port connects to arc ...*/
5127 for (j = 0; pp->connects[j] != NOARCPROTO; j++)
5128 if (pp->connects[j] == ap)
5129 {
5130 nis[cnt] = ni;
5131 pps[cnt] = pp;
5132 cnt++;
5133 }
5134 } else
5135 {
5136 portposition(ni, pp, &px, &py);
5137 dist = computedistance(x, y, px, py);
5138 if (bestni == NONODEINST || dist < bestdist)
5139 {
5140 bestni = ni;
5141 bestpp = pp;
5142 bestdist = dist;
5143 bestpx = px;
5144 bestpy = py;
5145 }
5146 }
5147 }
5148 break;
5149
5150 case FALSE:
5151 /* only accept valid wires */
5152 if (geom->entryaddr.ai->proto->tech == sch_tech)
5153 *ai = geom->entryaddr.ai;
5154 break;
5155 }
5156 }
5157
5158 /* special case: make it connect to anything that is near */
5159 if (cnt == 0 && bestni != NONODEINST)
5160 {
5161 /* create a new node in the proper position */
5162 np = getpinproto(ap);
5163 xs = np->highx - np->lowx; lx = x - xs/2; hx = lx + xs;
5164 ys = np->highy - np->lowy; ly = y - ys/2; hy = ly + ys;
5165 ni = io_edifiplacepin(np, lx, hx, ly, hy, 0, 0, cell);
5166 wid = ap->nominalwidth;
5167 bits = us_makearcuserbits(ap);
5168 newai = newarcinst(ap, wid, bits, ni, ni->proto->firstportproto, x, y, bestni, bestpp, bestpx, bestpy, cell);
5169 nis[cnt] = ni;
5170 pps[cnt] = ni->proto->firstportproto;
5171 cnt++;
5172 }
5173 return(cnt);
5174 }
5175
5176
5177 NODEINST *io_edifiplacepin(NODEPROTO *np, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy,
5178 INTBIG trans, INTBIG angle, NODEPROTO *parent)
5179 {
5180 REGISTER NODEINST *ni;
5181 REGISTER INTBIG cx, cy, sx, sy, icx, icy, isx, isy;
5182
5183 cx = (lx + hx) / 2;
5184 cy = (ly + hy) / 2;
5185 sx = hx - lx;
5186 sy = hy - ly;
5187
5188 for(ni = parent->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
5189 {
5190 if (ni->proto != np) continue;
5191 if (ni->rotation != angle || ni->transpose != trans) continue;
5192 icx = (ni->lowx + ni->highx) / 2;
5193 icy = (ni->lowy + ni->highy) / 2;
5194 isx = ni->highx - ni->lowx;
5195 isy = ni->highy - ni->lowy;
5196 if (icx != cx || icy != cy) continue;
5197 return(ni);
5198 }
5199 ni = newnodeinst(np, lx, hx, ly, hy, trans, angle, parent);
5200 return(ni);
5201 }
5202
5203