1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: tecschem.c
6  * Schematic technology
7  * Written by: Steven M. Rubin, Static Free Software
8  * Inspired by Erwin S. K. Liu, University of Calgary
9  *
10  * Copyright (c) 2000 Static Free Software.
11  *
12  * Electric(tm) is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Electric(tm) is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Electric(tm); see the file COPYING.  If not, write to
24  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25  * Boston, Mass 02111-1307, USA.
26  *
27  * Static Free Software
28  * 4119 Alpine Road
29  * Portola Valley, California 94028
30  * info@staticfreesoft.com
31  */
32 
33 /*
34  * The primitives of this technology can be parameterized as follows:
35  *
36  * "TRANSISTOR" uses "ATTR_width", "ATTR_length", and "ATTR_area" for size
37  * "RESISTOR"   uses "SCHEM_resistance"      for ohms
38  * "CAPACITOR"  uses "SCHEM_capacitance"     for capacitance
39  * "DIODE"      uses "SCHEM_diode"           for area
40  * "INDUCTOR"   uses "SCHEM_inductance"      for Henrys
41  * "BBOX"       uses "SCHEM_function"        for function
42  * "SOURCE"     uses "SIM_spice_model"       for the SPICE card
43  * "METER"      uses "SCHEM_meter_type"      for SPICE range
44  * "TWOPORT"    uses "SIM_spice_model"       for the SPICE card
45  */
46 
47 #include "global.h"
48 #include "database.h"
49 #include "egraphics.h"
50 #include "tech.h"
51 #include "tecschem.h"
52 #include "efunction.h"
53 #include "usr.h"
54 #include "network.h"
55 
56 #define SCALABLEGATES 1   /* uncomment for experimental scalable gate code */
57 
58 /* twentieths of a unit fractions */
59 #define D1	(WHOLE/20)		/* 0.05 */
60 #define FO	(WHOLE/40)		/* 0.025 */
61 #define D2	(WHOLE/10)		/* 0.10 */
62 #define D3	(WHOLE/20 * 3)	/* 0.15 */
63 #define D4	(WHOLE/5)		/* 0.20 */
64 #define D5	(WHOLE/4)		/* 0.25 */
65 #define D6	(WHOLE/10 * 3)	/* 0.30 */
66 #define D7	(WHOLE/20 * 7)	/* 0.35 */
67 #define D8	(WHOLE/5 * 2)	/* 0.40 */
68 #define D9	(WHOLE/20 * 9)	/* 0.45 */
69 #define D12	(WHOLE/5 * 3)	/* 0.60 */
70 #define D13	(WHOLE/20 * 13)	/* 0.65 */
71 #define D14	(WHOLE/10 * 7)	/* 0.70 */
72 #define D16	(WHOLE/5 * 4)	/* 0.80 */
73 
74 /* right of center by this amount */
75 #define CENTERR0Q   0,Q0	/* 0.25 */
76 #define CENTERR0T   0,T0	/* 0.75 */
77 #define CENTERR1Q   0,Q1	/* 1.25 */
78 #define CENTERR1T   0,T1	/* 1.75 */
79 #define CENTERR2Q   0,Q2	/* 2.25 */
80 #define CENTERR2T   0,T2	/* 2.75 */
81 #define CENTERR3Q   0,Q3	/* 3.25 */
82 #define CENTERR3T   0,T3	/* 3.75 */
83 
84 /* left of center by this amount */
85 #define CENTERL0Q   0,-Q0	/* 0.25 */
86 #define CENTERL0T   0,-T0	/* 0.75 */
87 #define CENTERL1Q   0,-Q1	/* 1.25 */
88 #define CENTERL1T   0,-T1	/* 1.75 */
89 #define CENTERL2Q   0,-Q2	/* 2.25 */
90 #define CENTERL2T   0,-T2	/* 2.75 */
91 #define CENTERL3Q   0,-Q3	/* 3.25 */
92 #define CENTERL3T   0,-T3	/* 3.75 */
93 #define CENTERL4Q   0,-Q4	/* 4.25 */
94 #define CENTERL9    0,-K9	/* 9.00 */
95 #define CENTERL10   0,-K10	/* 10.00 */
96 
97 /* up from center by this amount */
98 #define CENTERU0Q   0,Q0	/* 0.25 */
99 #define CENTERU0T   0,T0	/* 0.75 */
100 #define CENTERU1Q   0,Q1	/* 1.25 */
101 #define CENTERU1T   0,T1	/* 1.75 */
102 #define CENTERU2Q   0,Q2	/* 2.25 */
103 #define CENTERU2T   0,T2	/* 2.75 */
104 #define CENTERU3Q   0,Q3	/* 3.25 */
105 #define CENTERU3T   0,T3	/* 3.75 */
106 
107 /* down from center by this amount */
108 #define CENTERD0Q   0,-Q0	/* 0.25 */
109 #define CENTERD0T   0,-T0	/* 0.75 */
110 #define CENTERD1Q   0,-Q1	/* 1.25 */
111 #define CENTERD1T   0,-T1	/* 1.75 */
112 #define CENTERD2Q   0,-Q2	/* 2.25 */
113 #define CENTERD2T   0,-T2	/* 2.75 */
114 #define CENTERD3Q   0,-Q3	/* 3.25 */
115 #define CENTERD3T   0,-T3	/* 3.75 */
116 
117 /* this much from the center to the left edge */
118 #define LEFTBYP1   -D1,0		/* 0.1 */
119 #define LEFTBYP125 (-K1/15),0   /* 0.13333... */  /* wanted 0.125 but can't */
120 #define LEFTBYP166 (-K1/12),0	/* 0.16666... */
121 #define LEFTBYP2   -D2,0		/* 0.2 */
122 #define LEFTBYP25  (-D2-FO),0   /* 0.25 */
123 #define LEFTBYP3   -D3,0		/* 0.3 */
124 #define LEFTBYP33  (-K1/6),0	/* 0.3333... */
125 #define LEFTBYP35  -(D3+FO),0	/* 0.35 (21/60) */
126 #define LEFTBYP3666 -22,0		/* 0.3666... (22/60) */
127 #define LEFTBYP4   -D4,0		/* 0.4 */
128 #define LEFTBYP45  -(D4+FO),0   /* 0.45 (27/60) */
129 #define LEFTBYP5   -D5,0		/* 0.5 */
130 #define LEFTBYP6   -D6,0		/* 0.6 */
131 #define LEFTBYP6333  -38,0		/* 0.6333... (38/60) */
132 #define LEFTBYP66  (-K1/3),0	/* 0.6666... */
133 #define LEFTBYP7   -D7,0		/* 0.7 */
134 #define LEFTBYP75  (-D7-FO),0   /* 0.75 */
135 #define LEFTBYP8   -D8,0        /* 0.8 */
136 #define LEFTBYP875 -D9,0        /* 0.9 */ /* wanted 0.875 but can't */
137 #define LEFTBYP9   -D9,0		/* 0.9 */
138 #define LEFTBYP12  -D12,0		/* 1.2 */
139 #define LEFTBYP14  -D14,0		/* 1.4 */
140 #define LEFTBY1P6   -H0-D6,0	/* 1.6 */
141 
142 /* this much from the center to the right edge */
143 #define RIGHTBYP1   D1,0		/* 0.1       (6/60) */
144 #define RIGHTBYP125 (K1/15),0   /* 0.133...  (8/60) */ /* not precise */
145 #define RIGHTBYP166 (K1/12),0	/* 0.166...  (10/60) */
146 #define RIGHTBYP2   D2,0		/* 0.2       (12/60) */
147 #define RIGHTBYP25  (D2+FO),0   /* 0.25      (15/60) */
148 #define RIGHTBYP3   D3,0		/* 0.3       (18/60) */
149 #define RIGHTBYP33  (K1/6),0	/* 0.33...   (20/60) */
150 #define RIGHTBYP35  (D3+FO),0	/* 0.35      (21/60) */
151 #define RIGHTBYP3666  22,0		/* 0.3666... (22/60) */
152 #define RIGHTBYP3833  23,0		/* 0.3833... (23/60) */
153 #define RIGHTBYP4   D4,0		/* 0.4       (24/60) */
154 #define RIGHTBYP433  26,0		/* 0.433...  (26/60) */
155 #define RIGHTBYP45  (D4+FO),0   /* 0.45      (27/60) */
156 #define RIGHTBYP5   D5,0		/* 0.5       (30/60) */
157 #define RIGHTBYP5166   31,0		/* 0.5166... (31/60) */
158 #define RIGHTBYP55  (D5+FO),0	/* 0.55      (33/60) */
159 #define RIGHTBYP566   34,0		/* 0.566...  (34/60) */
160 #define RIGHTBYP6   D6,0		/* 0.6       (36/60) */
161 #define RIGHTBYP6166   37,0		/* 0.6166... (37/60) */
162 #define RIGHTBYP6333   38,0		/* 0.6333... (38/60) */
163 #define RIGHTBYP66  (K1/3),0	/* 0.66...   (40/60) */
164 #define RIGHTBYP7   D7,0		/* 0.7       (42/60) */
165 #define RIGHTBYP75  (D7+FO),0   /* 0.75      (45/60) */
166 #define RIGHTBYP8   D8,0        /* 0.8       (48/60) */
167 #define RIGHTBYP875 D9,0        /* 0.9       (54/60) */ /* not precise */
168 #define RIGHTBYP9   D9,0		/* 0.9       (54/60) */
169 
170 /* this much from the center to the bottom edge */
171 #define BOTBYP1    -D1,0		/* 0.1 */
172 #define BOTBYP125  (-K1/15),0   /* 0.133...  (8/60) */ /* not precise */
173 #define BOTBYP166  (-K1/12),0	/* 0.166... (10/60) */
174 #define BOTBYP2    -D2,0		/* 0.2 */
175 #define BOTBYP25   (-D2-FO),0	/* 0.25 */
176 #define BOTBYP3    -D3,0		/* 0.3 */
177 #define BOTBYP33   (-K1/6),0	/* 0.3333... */
178 #define BOTBYP375  -D4,0        /* 0.4 */
179 #define BOTBYP4    -D4,0		/* 0.4 */
180 #define BOTBYP5    -D5,0		/* 0.5 */
181 #define BOTBYP6    -D6,0		/* 0.6 */
182 #define BOTBYP66   (-K1/3),0	/* 0.6666... */
183 #define BOTBYP7    -D7,0		/* 0.7 */
184 #define BOTBYP75   (-D7-FO),0	/* 0.75 */
185 #define BOTBYP8    -D8,0		/* 0.8 */
186 #define BOTBYP875  -D9,0        /* 0.9 */ /* wanted 0.875 but can't */
187 #define BOTBYP9    -D9,0		/* 0.9 */
188 
189 /* this much from the center to the top edge */
190 #define TOPBYP1     D1,0		/* 0.1 */
191 #define TOPBYP2     D2,0		/* 0.2 */
192 #define TOPBYP25    (D2+FO),0   /* 0.25 */
193 #define TOPBYP3     D3,0		/* 0.3 */
194 #define TOPBYP33    (K1/6),0	/* 0.3333... */
195 #define TOPBYP4     D4,0		/* 0.4 */
196 #define TOPBYP5     D5,0		/* 0.5 */
197 #define TOPBYP5833  35,0		/* 0.58333... (35/60) */
198 #define TOPBYP6     D6,0		/* 0.6 */
199 #define TOPBYP66    (K1/3),0	/* 0.6666... */
200 #define TOPBYP7     D7,0		/* 0.7 */
201 #define TOPBYP75    45,0		/* 0.75       (45/60) */
202 #define TOPBYP8     D8,0		/* 0.8 */
203 #define TOPBYP866   (K1/12*5),0	/* 0.8666... */
204 #define TOPBYP875   D9,0        /* 0.9 */ /* wanted 0.875 but can't */
205 #define TOPBYP9     D9,0		/* 0.9 */
206 
207 /* the options table */
208 static COMCOMP schnegp = {NOKEYWORD, NOTOPLIST, NONEXTLIST, NOPARAMS,
209 	0, x_(" \t"), M_("size of negating bubble"), M_("show current size")};
210 static KEYWORD schopt[] =
211 {
212 	{x_("negating-bubble-diameter"),    1,{&schnegp,NOKEY,NOKEY,NOKEY,NOKEY}},
213 	{x_("disable-differential-ports"),  0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
214 	{x_("enable-differential-ports"),   0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
215 	TERMKEY
216 };
217 COMCOMP sch_parse = {schopt, NOTOPLIST, NONEXTLIST, NOPARAMS,
218 	0, x_(" \t"), M_("Schematic option"), M_("show current options")};
219 
220 TECHNOLOGY       *sch_tech;
221 INTBIG            sch_meterkey;			/* key for "SCHEM_meter_type" */
222 INTBIG            sch_diodekey;			/* key for "SCHEM_diode" */
223 INTBIG            sch_capacitancekey;	/* key for "SCHEM_capacitance" */
224 INTBIG            sch_resistancekey;	/* key for "SCHEM_resistance" */
225 INTBIG            sch_inductancekey;	/* key for "SCHEM_inductance" */
226 INTBIG            sch_functionkey;		/* key for "SCHEM_function" */
227 INTBIG            sch_spicemodelkey;	/* key for "SIM_spice_model" */
228 INTBIG            sch_globalnamekey;	/* key for "SCHEM_global_name" */
229 NODEPROTO        *sch_wirepinprim, *sch_buspinprim, *sch_wireconprim, *sch_bufprim,
230                  *sch_andprim, *sch_orprim, *sch_xorprim, *sch_ffprim, *sch_muxprim,
231                  *sch_bboxprim, *sch_switchprim, *sch_offpageprim, *sch_pwrprim,
232                  *sch_gndprim, *sch_sourceprim, *sch_transistorprim, *sch_resistorprim,
233                  *sch_capacitorprim, *sch_diodeprim, *sch_inductorprim, *sch_meterprim,
234 			     *sch_wellprim, *sch_substrateprim, *sch_twoportprim, *sch_transistor4prim,
235 			     *sch_globalprim;
236 ARCPROTO         *sch_wirearc, *sch_busarc;
237 static INTBIG     sch_bubblediameter = K1+D4;
238 
239 typedef struct
240 {
241 	/* for arc drawing */
242 	INTBIG        bubblebox, arrowbox;
243 
244 	/* for node drawing */
245 	TECH_POLYGON *layerlist;
246 
247 	/* control of the bar in a switch node */
248 	INTBIG        switchbarvalue;
249 
250 	/* control of the bus pin node */
251 	INTBIG        buspinlayer;
252 	INTBIG        buspinsize;
253 	INTBIG       *buspinpoints;
254 
255 	/* for extra steiner points on nodes */
256 	INTBIG        extrasteinerpoint;
257 	TECH_PORTS   *extrasteinerport[10];
258 } SCHPOLYLOOP;
259 static SCHPOLYLOOP sch_oneprocpolyloop;
260 
261 static PORTPROTO *sch_anddiffports, *sch_ordiffports, *sch_xordiffports;
262 INTBIG            sch_wirepinsizex;		/* X size if wire-pin primitives */
263 INTBIG            sch_wirepinsizey;		/* Y size if wire-pin primitives */
264 
265 INTBIG sch_intnodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win, POLYLOOP *pl, SCHPOLYLOOP *schpl);
266 void   sch_intshapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly, POLYLOOP *pl, SCHPOLYLOOP *schpl);
267 INTBIG sch_intarcpolys(ARCINST *ai, WINDOWPART *win, POLYLOOP *pl, SCHPOLYLOOP *schpl);
268 void   sch_intshapearcpoly(ARCINST *ai, INTBIG box, POLYGON *poly, POLYLOOP *pl, SCHPOLYLOOP *schpl);
269 
270 /******************** LAYERS ********************/
271 
272 #define MAXLAYERS  4		/* total layers below      */
273 
274 #define LARC       0		/* wire                    */
275 #define LBUS       1		/* bus                     */
276 #define LNODE      2		/* schematic block and pin */
277 #define LTEXT      3		/* documentation           */
278 
279 static GRAPHICS sch_a_lay = {LAYERO,BLUE, SOLIDC, SOLIDC,
280 	{0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
281 	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
282 static GRAPHICS sch_b_lay = {LAYERT3,COLORT3, SOLIDC, PATTERNED,
283 /* bus layer */			{0x2222, /*   X   X   X   X  */
284 						0x0000,  /*                  */
285 						0x8888,  /* X   X   X   X    */
286 						0x0000,  /*                  */
287 						0x2222,  /*   X   X   X   X  */
288 						0x0000,  /*                  */
289 						0x8888,  /* X   X   X   X    */
290 						0x0000,  /*                  */
291 						0x2222,  /*   X   X   X   X  */
292 						0x0000,  /*                  */
293 						0x8888,  /* X   X   X   X    */
294 						0x0000,  /*                  */
295 						0x2222,  /*   X   X   X   X  */
296 						0x0000,  /*                  */
297 						0x8888,  /* X   X   X   X    */
298 						0x0000}, /*                  */
299 						NOVARIABLE, 0};
300 static GRAPHICS sch_n_lay = {LAYERO, RED, SOLIDC, SOLIDC,
301 	{0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
302 	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
303 static GRAPHICS sch_t_lay = {LAYERO, CELLTXT, SOLIDC, SOLIDC,
304 	{0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
305 	0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
306 
307 /* these tables must be updated together */
308 GRAPHICS *sch_layers[MAXLAYERS+1] = {&sch_a_lay, &sch_b_lay, &sch_n_lay,
309 	&sch_t_lay, NOGRAPHICS};
310 static CHAR *sch_layer_names[MAXLAYERS] = {x_("Arc"), x_("Bus"), x_("Node"), x_("Text")};
311 static INTBIG sch_layer_function[MAXLAYERS] = {LFMETAL1, LFBUS, LFART, LFART};
312 static CHAR *sch_layer_letters[MAXLAYERS] = {x_("a"), x_("b"), x_("n"), x_("t")};
313 
314 /******************** ARCS ********************/
315 
316 #define ARCPROTOCOUNT   2
317 
318 #define AWIRE           0	/* wire               */
319 #define ABUS            1	/* bus                */
320 
321 /* wire arc */
322 static TECH_ARCLAY sch_al_w[] = { {LARC,0,FILLED}, {LARC,0,CIRCLE}, {LARC,0,VECTORS}};
323 static TECH_ARCS sch_a_w = {
324 	x_("wire"),0,AWIRE,NOARCPROTO,													/* name */
325 	1,sch_al_w,																		/* layers */
326 	(APMETAL1<<AFUNCTIONSH)|WANTFIXANG|WANTCANTSLIDE|(45<<AANGLEINCSH)};			/* userbits */
327 
328 /* bus arc */
329 static TECH_ARCLAY sch_al_b[] = { {LBUS,0,FILLED}, {LBUS,0,CIRCLE}, {LARC,0,VECTORS}};
330 static TECH_ARCS sch_a_b = {
331 	x_("bus"),K1,ABUS,NOARCPROTO,													/* name */
332 	1,sch_al_b,																		/* layers */
333 	(APBUS<<AFUNCTIONSH)|WANTFIXANG|WANTCANTSLIDE|WANTNOEXTEND|(45<<AANGLEINCSH)};	/* userbits */
334 
335 TECH_ARCS *sch_arcprotos[ARCPROTOCOUNT+1] = {&sch_a_w, &sch_a_b, ((TECH_ARCS *)-1)};
336 
337 /******************** PORTINST CONNECTIONS ********************/
338 
339 /* these values are replaced with actual arcproto addresses */
340 static INTBIG sch_pc_wire[]   = {-1, AWIRE, ALLGEN, -1};
341 static INTBIG sch_pc_bus[]    = {-1, ABUS, ALLGEN, -1};
342 static INTBIG sch_pc_either[] = {-1, AWIRE, ABUS, ALLGEN, -1};
343 
344 /******************** NODES ********************/
345 
346 #define NODEPROTOCOUNT    26
347 
348 #define NWIREPIN      1		/* wire pin */
349 #define NBUSPIN       2		/* bus pin */
350 #define NWIRECON      3		/* wire connector */
351 #define NBUF          4		/* general BUFFER */
352 #define NAND          5		/* general AND */
353 #define NOR           6		/* general OR */
354 #define NXOR          7		/* general XOR */
355 #define NFF           8		/* general FLIP FLOP */
356 #define NMUX          9		/* general MUX */
357 #define NBBOX        10		/* black box */
358 #define NSWITCH      11		/* switch */
359 #define NOFFPAGE     12		/* off page connector */
360 #define NPWR         13		/* power */
361 #define NGND         14		/* ground */
362 #define NSOURCE      15		/* source (voltage, current) */
363 #define NTRANSISTOR  16		/* transistor */
364 #define NRESISTOR    17		/* resistor */
365 #define NCAPACITOR   18		/* capacitor */
366 #define NDIODE       19		/* diode */
367 #define NINDUCTOR    20		/* inductor */
368 #define NMETER       21		/* meter */
369 #define NWELL        22		/* well connection */
370 #define NSUBSTRATE   23		/* substrate connection */
371 #define NTWOPORT     24		/* generic two-port block */
372 #define NTRANSISTOR4 25		/* four-port transistor */
373 #define NGLOBALSIG   26		/* global signal */
374 
375 /******************** POLYGONS ********************/
376 
377 static CHAR sch_NULLSTR[] = {x_("")};
378 static CHAR sch_D[] = {x_("D")};
379 static CHAR sch_E[] = {x_("E")};
380 static CHAR sch_J[] = {x_("J")};
381 static CHAR sch_K[] = {x_("K")};
382 static CHAR sch_Q[] = {x_("Q")};
383 static CHAR sch_R[] = {x_("R")};
384 static CHAR sch_S[] = {x_("S")};
385 static CHAR sch_T[] = {x_("T")};
386 static CHAR sch_V[] = {x_("V")};
387 static CHAR sch_PR[] = {x_("PR")};
388 static CHAR sch_QB[] = {x_("QB")};
389 
390 static INTBIG sch_g_pindisc[]    = {CENTER,    CENTER,    RIGHTEDGE, CENTER};
391 static INTBIG sch_g_buspindisc[] = {CENTER,    CENTER,    RIGHTBYP5, CENTER};
392 static INTBIG sch_g_bustapdisc[] = {CENTER,    CENTER,    RIGHTBYP25,CENTER};
393 static CHAR  *sch_g_wireconj[]   = {0,  0,     0, 0,      sch_J};
394 static INTBIG sch_g_inv[]        = {RIGHTBYP66,CENTER,    LEFTEDGE,  TOPBYP875,
395 								    LEFTEDGE,  BOTBYP875};
396 static INTBIG sch_g_and[]        = {CENTERR0H, CENTER,    CENTERR0H, CENTERU3,
397 								    CENTERR0H, CENTERD3};
398 static INTBIG sch_g_andbox[]     = {CENTERR0H, CENTERU3,  CENTERL4,  CENTERU3,
399 								    CENTERL4,  TOPEDGE,   CENTERL4,  BOTEDGE,
400 								    CENTERL4,  CENTERD3,  CENTERR0H, CENTERD3};
401 static INTBIG sch_g_or[]         = {CENTERL4,  TOPEDGE,   CENTERL4,  CENTERU3,
402 								    CENTERL4,  CENTERU3,  CENTERL0T, CENTERU3,
403 								    CENTERL4,  BOTEDGE,   CENTERL4,  CENTERD3,
404 								    CENTERL4,  CENTERD3,  CENTERL0T, CENTERD3};
405 static INTBIG sch_g_ort[]        = {CENTERL0T, CENTERD3,  CENTERL0T, CENTERU3,
406 								    CENTERR4H, CENTER};
407 static INTBIG sch_g_orb[]        = {CENTERL0T, CENTERU3,  CENTERR4H, CENTER,
408 								    CENTERL0T, CENTERD3};
409 static INTBIG sch_g_orl[]        = {CENTERL9,  CENTER,    CENTERL4,  CENTERU3,
410 								    CENTERL4,  CENTERD3};
411 static INTBIG sch_g_xor[]        = {CENTERL10, CENTER,    CENTERL5,  CENTERU3,
412 								    CENTERL5,  CENTERD3};
413 static INTBIG sch_g_ffbox[]      = {LEFTEDGE,  BOTEDGE,   RIGHTEDGE, TOPEDGE};
414 static INTBIG sch_g_ffarrow[]    = {LEFTEDGE,  BOTBYP2,   LEFTBYP7,  CENTER,
415 								    LEFTEDGE,  TOPBYP2};
416 static CHAR *sch_g_fftextd[]    = {(CHAR *)-H0,  0,  (CHAR *)D4,0,   (CHAR *)-H0,  0,  (CHAR *)D8,0,
417 								   (CHAR *)-D4,0,  (CHAR *)D8,0,   (CHAR *)-D4,0,  (CHAR *)D4,0,
418 								   sch_D};
419 static CHAR *sch_g_fftexte[]    = {(CHAR *)-H0,  0,  (CHAR *)-D4,0,   (CHAR *)-H0,  0,  (CHAR *)-D8,0,
420 								   (CHAR *)-D4,0,  (CHAR *)-D8,0,   (CHAR *)-D4,0,  (CHAR *)-D4,0,
421 								   sch_E};
422 static CHAR *sch_g_fftextq[]    = {(CHAR *)H0,  0, (CHAR *)D4,0,   (CHAR *)H0,  0, (CHAR *)D8,0,
423 								   (CHAR *)D4,0, (CHAR *)D8,0,   (CHAR *)D4,0, (CHAR *)D4,0,
424 								   sch_Q};
425 static CHAR *sch_g_fftextqb[]   = {(CHAR *)H0,  0, (CHAR *)-D4,0,   (CHAR *)H0,  0, (CHAR *)-D8,0,
426 								   (CHAR *)D4,0, (CHAR *)-D8,0,   (CHAR *)D4,0, (CHAR *)-D4,0,
427 								   sch_QB};
428 static CHAR *sch_g_fftextpr[]   = {(CHAR *)-D6,0,  (CHAR *)D6,0,   (CHAR *)-D6,0,  (CHAR *)H0,  0,
429 								   (CHAR *)D6,0, (CHAR *)H0,  0,   (CHAR *)D6,0, (CHAR *)D6,0,
430 								   sch_PR};
431 static CHAR *sch_g_fftextclr[]  = {(CHAR *)-D6,0,  (CHAR *)-D6,0,   (CHAR *)-D6,0,  (CHAR *)-H0,  0,
432 								   (CHAR *)D6,0, (CHAR *)-H0,  0,   (CHAR *)D6,0, (CHAR *)-D6,0,
433 								   0 /* "CLR" */};
434 static CHAR *sch_g_meterv[]     = {(CHAR *)-H0,  0,  (CHAR *)-H0,  0,   (CHAR *)H0,  0, (CHAR *)H0,  0,
435 								   sch_V};
436 static INTBIG sch_g_ffn[]        = {LEFTBYP6,  TOPBYP2,   LEFTBYP4,  TOPBYP2,
437 								    LEFTBYP4,  BOTBYP2,   LEFTBYP2,  BOTBYP2};
438 static INTBIG sch_g_ffp[]        = {LEFTBYP6,  BOTBYP2,   LEFTBYP4,  BOTBYP2,
439 								    LEFTBYP4,  TOPBYP2,   LEFTBYP2,  TOPBYP2};
440 static INTBIG sch_g_ffms[]       = {LEFTBYP6,  BOTBYP2,   LEFTBYP4,  BOTBYP2,
441 								    LEFTBYP4,  TOPBYP2,   LEFTBYP2,  TOPBYP2,
442 								    LEFTBYP2,  BOTBYP2,   CENTER,    BOTBYP2};
443 static INTBIG sch_g_mux[]        = {RIGHTBYP8, TOPBYP75,  RIGHTBYP8, BOTBYP75,
444 								    LEFTBYP8,  BOTEDGE,   LEFTBYP8,  TOPEDGE};
445 static INTBIG sch_g_bbox[]       = {LEFTEDGE,  BOTEDGE,   RIGHTEDGE, TOPEDGE};
446 static INTBIG sch_g_switchin[]   = {RIGHTIN1,  CENTER,    RIGHTIN1Q, CENTER};
447 static INTBIG sch_g_switchbar[]  = {RIGHTIN1,  CENTER,    LEFTIN1,   CENTER};
448 static INTBIG sch_g_switchout[]  = {LEFTIN1,   BOTIN0H,   LEFTIN0T,  BOTIN0H};
449 static INTBIG sch_g_offpage[]    = {LEFTEDGE,  BOTEDGE,   LEFTEDGE,  TOPEDGE,
450 								    RIGHTBYP5, TOPEDGE,   RIGHTEDGE, CENTER,
451 								    RIGHTBYP5, BOTEDGE};
452 static INTBIG sch_g_pwr1[]       = {CENTER,    CENTER,    CENTER,    TOPEDGE};
453 static INTBIG sch_g_pwr2[]       = {CENTER,    CENTER,    CENTER,    TOPBYP75};
454 static INTBIG sch_g_gnd[]        = {CENTER,    CENTER,    CENTER,    TOPEDGE,
455 								    LEFTEDGE,  CENTER,    RIGHTEDGE, CENTER,
456 								    LEFTBYP75, BOTBYP25,  RIGHTBYP75,BOTBYP25,
457 								    LEFTBYP5,  BOTBYP5,   RIGHTBYP5, BOTBYP5,
458 								    LEFTBYP25, BOTBYP75,  RIGHTBYP25,BOTBYP75,
459 								    CENTER,    BOTEDGE,   CENTER,    BOTEDGE};
460 static INTBIG sch_g_resist[]     = {LEFTBYP66, CENTER,    LEFTBYP6,  CENTER,
461 								    LEFTBYP5,  TOPEDGE,   LEFTBYP3,  BOTEDGE,
462 								    LEFTBYP1,  TOPEDGE,   RIGHTBYP1, BOTEDGE,
463 								    RIGHTBYP3, TOPEDGE,   RIGHTBYP5, BOTEDGE,
464 								    RIGHTBYP6, CENTER,    RIGHTBYP66,CENTER};
465 static INTBIG sch_g_capac[]      = {LEFTEDGE,  TOPBYP2,   RIGHTEDGE, TOPBYP2,
466 								    LEFTEDGE,  BOTBYP2,   RIGHTEDGE, BOTBYP2,
467 								    CENTER,    TOPBYP2,   CENTER,    TOPEDGE,
468 								    CENTER,    BOTBYP2,   CENTER,    BOTEDGE};
469 static INTBIG sch_g_capace[]     = {RIGHTBYP2, BOTBYP6,   RIGHTBYP6, BOTBYP6,
470 								    RIGHTBYP4, BOTBYP4,   RIGHTBYP4, BOTBYP8};
471 static INTBIG sch_g_source[]     = {CENTER,    CENTER,    RIGHTEDGE, CENTER};
472 static INTBIG sch_g_sourcepl[]   = {LEFTBYP3,  TOPBYP6,   RIGHTBYP3, TOPBYP6,
473 								    CENTER,    TOPBYP3,   CENTER,    TOPBYP9};
474 static INTBIG sch_g_mos[]        = {LEFTEDGE,  BOTEDGE,   LEFTBYP75, BOTEDGE,
475 								    LEFTBYP75, BOTBYP5,   RIGHTBYP75,BOTBYP5,
476 								    RIGHTBYP75,BOTEDGE,   RIGHTEDGE, BOTEDGE};
477 static INTBIG sch_g_trantop[]    = {LEFTBYP75, BOTBYP25,  RIGHTBYP75,BOTBYP25};
478 static INTBIG sch_g_nmos[]       = {CENTER,    BOTBYP25,  CENTER,    TOPIN1};
479 static INTBIG sch_g_nmos4[]      = {LEFTBYP5,  BOTBYP5,   LEFTBYP5,  BOTEDGE,
480 									LEFTBYP5,  BOTBYP5,   LEFTBYP35, BOTBYP75,
481 									LEFTBYP5,  BOTBYP5,   LEFTBYP66, BOTBYP75};
482 static INTBIG sch_g_dmos4[]      = {LEFTBYP5,  BOTBYP75,  LEFTBYP5,  BOTEDGE,
483 									LEFTBYP5,  BOTBYP75,  LEFTBYP35, BOTBYP9,
484 									LEFTBYP5,  BOTBYP75,  LEFTBYP66, BOTBYP9};
485 static INTBIG sch_g_pmos4[]      = {LEFTBYP5,  BOTBYP5,   LEFTBYP5,  BOTEDGE,
486 									LEFTBYP5,  BOTEDGE,   LEFTBYP35, BOTBYP75,
487 									LEFTBYP5,  BOTEDGE,   LEFTBYP66, BOTBYP75};
488 static INTBIG sch_g_bip4[]       = {LEFTBYP5,  BOTEDGE,   CENTER,    BOTBYP25};
489 static INTBIG sch_g_nmes4[]      = {LEFTBYP5,  BOTBYP25,  LEFTBYP5,  BOTEDGE,
490 									LEFTBYP5,  BOTBYP25,  LEFTBYP35, BOTBYP5,
491 									LEFTBYP5,  BOTBYP25,  LEFTBYP66, BOTBYP5};
492 static INTBIG sch_g_pmes4[]      = {LEFTBYP5,  BOTBYP25,  LEFTBYP5,  BOTEDGE,
493 									LEFTBYP5,  BOTEDGE,   LEFTBYP35, BOTBYP75,
494 									LEFTBYP5,  BOTEDGE,   LEFTBYP66, BOTBYP75};
495 static INTBIG sch_g_pmos[]       = {CENTER,    TOPBYP25,  CENTER,    TOPIN1};
496 static INTBIG sch_g_pmoscir[]    = {CENTER,    CENTER,    CENTER,    BOTBYP25};
497 static INTBIG sch_g_dmos[]       = {LEFTBYP75, BOTBYP75,  RIGHTBYP75,BOTBYP5};
498 static INTBIG sch_g_btran1[]     = {LEFTEDGE,  BOTEDGE,   LEFTBYP75, BOTEDGE,
499 								    LEFTBYP25, BOTBYP25,  RIGHTBYP25,BOTBYP25,
500 								    RIGHTBYP75,BOTEDGE,   RIGHTEDGE, BOTEDGE};
501 static INTBIG sch_g_btran2[]     = {LEFTBYP75, BOTBYP75,  LEFTBYP75, BOTEDGE,
502 								    LEFTBYP5,  BOTBYP875};
503 static INTBIG sch_g_btran3[]     = {LEFTBYP5,  BOTBYP375, LEFTBYP25, BOTBYP25,
504 								    LEFTBYP25, BOTBYP5};
505 static INTBIG sch_g_btran4[]     = {LEFTEDGE,  BOTEDGE,   LEFTBYP75, BOTEDGE,
506 									LEFTBYP75, BOTEDGE,   LEFTBYP75, BOTBYP25,
507 									LEFTBYP875,BOTBYP25,  RIGHTBYP875,BOTBYP25,
508 									RIGHTBYP75,BOTBYP25,  RIGHTBYP75,BOTEDGE,
509 									RIGHTBYP75,BOTEDGE,   RIGHTEDGE, BOTEDGE};
510 static INTBIG sch_g_btran5[]     = {LEFTBYP125,CENTER,    CENTER,    BOTBYP25,
511 								    RIGHTBYP125,CENTER};
512 static INTBIG sch_g_btran6[]     = {LEFTBYP125,CENTER,    CENTER,    TOPBYP25,
513 								    RIGHTBYP125,CENTER};
514 static INTBIG sch_g_btran7[]     = {LEFTEDGE,  BOTEDGE,   LEFTBYP75, BOTEDGE,
515 								    LEFTBYP75, BOTEDGE,   LEFTBYP75, BOTBYP25,
516 								    LEFTBYP875,BOTBYP25,  LEFTBYP5,  BOTBYP25,
517 								    LEFTBYP25, BOTBYP25,  RIGHTBYP25,BOTBYP25,
518 								    RIGHTBYP5, BOTBYP25,  RIGHTBYP875,BOTBYP25,
519 								    RIGHTBYP75,BOTBYP25,  RIGHTBYP75,BOTEDGE,
520 								    RIGHTBYP75,BOTEDGE,   RIGHTEDGE, BOTEDGE};
521 static INTBIG sch_g_diode1[]     = {LEFTEDGE,  TOPBYP5,   RIGHTEDGE, TOPBYP5,
522 								    CENTER,    TOPBYP5,   CENTER,    TOPEDGE,
523 								    CENTER,    BOTBYP5,   CENTER,    BOTEDGE};
524 static INTBIG sch_g_diode2[]     = {LEFTEDGE,  BOTBYP5,   RIGHTEDGE, BOTBYP5,
525 								    CENTER,    TOPBYP5};
526 static INTBIG sch_g_diode3[]     = {LEFTEDGE,  TOPBYP75,  LEFTEDGE,  TOPBYP5,
527 								    LEFTEDGE,  TOPBYP5,   RIGHTEDGE, TOPBYP5,
528 								    RIGHTEDGE, TOPBYP5,   RIGHTEDGE, TOPBYP25,
529 								    CENTER,    TOPBYP5,   CENTER,    TOPEDGE,
530 								    CENTER,    BOTBYP5,   CENTER,    BOTEDGE};
531 static INTBIG sch_g_induct1[]    = {CENTER,    TOPEDGE,   CENTER,    BOTEDGE};
532 static INTBIG sch_g_induct2[]    = {LEFTBYP5,  TOPBYP33,  CENTER,    TOPBYP33};
533 static INTBIG sch_g_induct3[]    = {LEFTBYP5,  CENTER,    CENTER,    CENTER};
534 static INTBIG sch_g_induct4[]    = {LEFTBYP5,  BOTBYP33,  CENTER,    BOTBYP33};
535 static INTBIG sch_g_meter[]      = {CENTER,    CENTER,    RIGHTEDGE, CENTER};
536 static INTBIG sch_g_well[]       = {LEFTEDGE,  BOTEDGE,   RIGHTEDGE, BOTEDGE,
537 								    CENTER,    TOPEDGE,   CENTER,    BOTEDGE};
538 static INTBIG sch_g_global1[]    = {LEFTEDGE,  CENTER,    CENTER,    TOPEDGE,
539 								    RIGHTEDGE, CENTER,    CENTER,    BOTEDGE};
540 static INTBIG sch_g_global2[]    = {LEFTBYP9,  CENTER,    CENTER,    TOPBYP9,
541 								    RIGHTBYP9, CENTER,    CENTER,    BOTBYP9};
542 static INTBIG sch_g_substrate[]  = {CENTER,    CENTER,    CENTER,    TOPEDGE,
543 								    LEFTEDGE,  CENTER,    RIGHTEDGE, CENTER,
544 								    LEFTEDGE,  CENTER,    CENTER,    BOTEDGE,
545 								    RIGHTEDGE, CENTER,    CENTER,    BOTEDGE};
546 
547 static INTBIG sch_g_twocsarr[]   = {RIGHTBYP3833,TOPBYP33,RIGHTBYP3833,BOTBYP33,
548 								    RIGHTBYP3833,BOTBYP33,RIGHTBYP33,BOTBYP166,
549 								    RIGHTBYP3833,BOTBYP33,RIGHTBYP433,BOTBYP166};
550 static INTBIG sch_g_twoulpl[]    = {LEFTBYP35, TOPBYP66,  LEFTBYP45, TOPBYP66,
551 								    LEFTBYP4,  TOPBYP5833,LEFTBYP4,  TOPBYP75};
552 static INTBIG sch_g_twourpl[]    = {RIGHTBYP35,TOPBYP66,  RIGHTBYP45,TOPBYP66,
553 								    RIGHTBYP4, TOPBYP5833,RIGHTBYP4, TOPBYP75};
554 static INTBIG sch_g_twourrpl[]   = {RIGHTBYP5166,TOPBYP66,RIGHTBYP6166,TOPBYP66,
555 								    RIGHTBYP566,TOPBYP5833,RIGHTBYP566,TOPBYP75};
556 static INTBIG sch_g_twobox[]     = {LEFTBYP8,  BOTEDGE,   RIGHTBYP8, TOPEDGE};
557 static INTBIG sch_g_twogwire[]   = {LEFTEDGE,  TOPBYP66,  LEFTBYP8,  TOPBYP66,
558 								    LEFTEDGE,  BOTBYP66,  LEFTBYP8,  BOTBYP66,
559 								    RIGHTEDGE, TOPBYP66,  RIGHTBYP8, TOPBYP66,
560 								    RIGHTEDGE, BOTBYP66,  RIGHTBYP8, BOTBYP66};
561 static INTBIG sch_g_twonormwire[]= {LEFTEDGE,  TOPBYP66,  LEFTBYP6,  TOPBYP66,
562 								    LEFTEDGE,  BOTBYP66,  LEFTBYP6,  BOTBYP66,
563 								    RIGHTEDGE, TOPBYP66,  RIGHTBYP6, TOPBYP66,
564 								    RIGHTBYP6, TOPBYP66,  RIGHTBYP6, TOPBYP3,
565 								    RIGHTEDGE, BOTBYP66,  RIGHTBYP6, BOTBYP66,
566 								    RIGHTBYP6, BOTBYP66,  RIGHTBYP6, BOTBYP3};
567 static INTBIG sch_g_twoccwire[]  = {LEFTBYP6,  TOPBYP66,  LEFTBYP6,  BOTBYP66};
568 static INTBIG sch_g_twocswire[]  = {RIGHTBYP6, TOPBYP3,   RIGHTBYP45,CENTER,
569 								    RIGHTBYP45,CENTER,    RIGHTBYP6, BOTBYP3,
570 								    RIGHTBYP6, BOTBYP3,   RIGHTBYP75,CENTER,
571 								    RIGHTBYP75,CENTER,    RIGHTBYP6, TOPBYP3};
572 static INTBIG sch_g_twovsc[]     = {RIGHTBYP6, CENTER,    RIGHTBYP6, TOPBYP3};
573 static INTBIG sch_g_twotr1[]     = {CENTER,    CENTER,    LEFTBYP8,  BOTEDGE,
574 								    LEFTBYP8,  TOPEDGE};
575 static INTBIG sch_g_twotr2[]     = {LEFTBY1P6, CENTER,    LEFTBYP8,  TOPEDGE,
576 								    LEFTBYP8,  BOTEDGE};
577 static INTBIG sch_g_twotr3[]     = {CENTER,    CENTER,    RIGHTBYP8, TOPEDGE,
578 								    RIGHTBYP8, BOTEDGE};
579 static INTBIG sch_g_twotrbox[]   = {LEFTBYP8,  TOPEDGE,   RIGHTBYP8, TOPEDGE,
580 								    LEFTBYP8,  BOTEDGE,   RIGHTBYP8, BOTEDGE};
581 static INTBIG sch_g_twotrwire[]  = {LEFTEDGE,  TOPBYP66,  LEFTBYP8,  TOPBYP66,
582 								    LEFTEDGE,  BOTBYP66,  LEFTBYP8,  BOTBYP66,
583 								    RIGHTEDGE, TOPBYP66,  RIGHTBYP9, TOPBYP66,
584 								    RIGHTEDGE, BOTBYP66,  RIGHTBYP9, BOTBYP66};
585 
586 /******************** NODES ********************/
587 
588 /* wire-pin */
589 static TECH_PORTS sch_wirepin_p[] = {				/* ports */
590 	{sch_pc_wire, x_("wire"), NOPORTPROTO, (180<<PORTARANGESH),
591 		CENTER, CENTER, CENTER, CENTER}};
592 static TECH_POLYGON sch_wirepin_l[] = {				/* layers */
593 	{LARC, 0, 2, DISC, POINTS, sch_g_pindisc}};
594 static TECH_NODES sch_wirepin = {
595 	x_("Wire_Pin"),NWIREPIN,NONODEPROTO,			/* name */
596 	H0,H0,											/* size */
597 	1,sch_wirepin_p,								/* ports */
598 	1,sch_wirepin_l,								/* layers */
599 	(NPPIN<<NFUNCTIONSH)|NSQUARE|WIPEON1OR2,		/* userbits */
600 	0,0,0,0,0,0,0,0,0};								/* characteristics */
601 
602 /* bus-pin */
603 static TECH_PORTS sch_buspin_p[] = {				/* ports */
604 	{sch_pc_either, x_("bus"), NOPORTPROTO, (180<<PORTARANGESH),
605 		CENTER, CENTER, CENTER, CENTER}};
606 static TECH_POLYGON sch_buspin_l[] = {				/* layers */
607 	{LBUS, 0, 2, DISC, POINTS, sch_g_buspindisc},
608 	{LARC, 0, 2, DISC, POINTS, sch_g_bustapdisc}};
609 static TECH_NODES sch_buspin = {
610 	x_("Bus_Pin"),NBUSPIN,NONODEPROTO,				/* name */
611 	K2,K2,											/* size */
612 	1,sch_buspin_p,									/* ports */
613 	2,sch_buspin_l,									/* layers */
614 	(NPPIN<<NFUNCTIONSH)|NSQUARE|WIPEON1OR2|NHASOPA|(1<<NFIRSTOPASH),	/* userbits */
615 	0,0,0,0,0,0,0,0,0};								/* characteristics */
616 
617 /* wire-con */
618 static TECH_PORTS sch_wirecon_p[] = {				/* ports */
619 	{sch_pc_either, x_("wire"), NOPORTPROTO, (180<<PORTARANGESH)|PORTISOLATED,
620 		LEFTIN0H, BOTIN0H, RIGHTIN0H, TOPIN0H}};
621 static TECH_POLYGON sch_wirecon_l[] = {				/* layers */
622 	{LNODE, 0,                4, CLOSEDRECT, BOX, sch_g_bbox},
623 	{LTEXT, TXTSETQLAMBDA(8), 1, TEXTCENT, POINTS, (INTBIG *)sch_g_wireconj}};
624 static TECH_NODES sch_wirecon = {
625 	x_("Wire_Con"),NWIRECON,NONODEPROTO,			/* name */
626 	K2,K2,											/* size */
627 	1,sch_wirecon_p,								/* ports */
628 	2,sch_wirecon_l,								/* layers */
629 	(NPCONNECT<<NFUNCTIONSH),						/* userbits */
630 	0,0,0,0,0,0,0,0,0};								/* characteristics */
631 
632 /* general buffer */
633 static TECH_PORTS sch_buf_p[] = {					/* ports */
634 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(0<<PORTARANGESH)|
635 		(0<<PORTNETSH)|INPORT, LEFTEDGE, CENTER, LEFTEDGE, CENTER},
636 	{sch_pc_wire, x_("c"), NOPORTPROTO, (270<<PORTANGLESH)|(0<<PORTARANGESH)|
637 		(1<<PORTNETSH)|INPORT, CENTER, BOTBYP33, CENTER, BOTBYP33},
638 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
639 		(2<<PORTNETSH)|OUTPORT, RIGHTBYP66, CENTER, RIGHTBYP66, CENTER}};
640 static TECH_POLYGON sch_buf_l[] = {					/* layers */
641 	{LNODE, 0, 3, CLOSED, POINTS, sch_g_inv}};
642 static TECH_NODES sch_buf = {
643 	x_("Buffer"), NBUF, NONODEPROTO,				/* name */
644 	K6,K6,											/* size */
645 	3,sch_buf_p,									/* ports */
646 	1,sch_buf_l,									/* layers */
647 	(NPBUFFER<<NFUNCTIONSH),						/* userbits */
648 	0,0,0,0,0,0,0,0,0};								/* characteristics */
649 
650 /* general and */
651 static TECH_PORTS sch_and_p[] = {					/* ports */
652 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(0<<PORTARANGESH)|
653 		(0<<PORTNETSH)|INPORT|PORTISOLATED, CENTERL4,BOTEDGE,CENTERL4,TOPEDGE},
654 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
655 		(1<<PORTNETSH)|OUTPORT, CENTERR3H, CENTER, CENTERR3H, CENTER},
656 	{sch_pc_either, x_("yt"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
657 		(2<<PORTNETSH)|OUTPORT, CENTERR2T, CENTERU2, CENTERR2T, CENTERU2},
658 	{sch_pc_either, x_("yc"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
659 		(3<<PORTNETSH)|OUTPORT, CENTERR2T, CENTERD2, CENTERR2T, CENTERD2}};
660 static TECH_POLYGON sch_and_l[] = {					/* layers */
661 	{LNODE, 0, 3, CIRCLEARC,  POINTS, sch_g_and},
662 	{LNODE, 0, 6, OPENED,     POINTS, sch_g_andbox}};
663 static TECH_NODES sch_and = {
664 	x_("And"), NAND, NONODEPROTO,					/* name */
665 	K8,K6,											/* size */
666 	4,sch_and_p,									/* ports */
667 	2,sch_and_l,									/* layers */
668 	(NPGATEAND<<NFUNCTIONSH),						/* userbits */
669 	0,0,0,0,0,0,0,0,0};								/* characteristics */
670 
671 /* general or */
672 static TECH_PORTS sch_or_p[] = {					/* ports */
673 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(0<<PORTARANGESH)|
674 		(0<<PORTNETSH)|INPORT|PORTISOLATED, CENTERL4,BOTEDGE, CENTERL3,TOPEDGE},
675 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
676 		(1<<PORTNETSH)|OUTPORT, CENTERR4H, CENTER, CENTERR4H, CENTER},
677 	{sch_pc_either, x_("yt"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
678 		(2<<PORTNETSH)|OUTPORT, CENTERR2+D13, CENTERU2, CENTERR2+D13, CENTERU2},
679 	{sch_pc_either, x_("yc"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
680 		(3<<PORTNETSH)|OUTPORT, CENTERR2+D13, CENTERD2, CENTERR2+D13, CENTERD2}};
681 static TECH_POLYGON sch_or_l[] = {					/* layers */
682 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_orl},
683 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_ort},
684 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_orb},
685 	{LNODE, 0, 8, VECTORS,   POINTS, sch_g_or}};
686 static TECH_NODES sch_or = {
687 	x_("Or"), NOR, NONODEPROTO,						/* name */
688 	K10,K6,											/* size */
689 	4,sch_or_p,										/* ports */
690 	4,sch_or_l,										/* layers */
691 	(NPGATEOR<<NFUNCTIONSH),						/* userbits */
692 	0,0,0,0,0,0,0,0,0};								/* characteristics */
693 
694 /* general xor */
695 static TECH_PORTS sch_xor_p[] = {					/* ports */
696 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(0<<PORTARANGESH)|
697 		(0<<PORTNETSH)|INPORT|PORTISOLATED, CENTERL4,BOTEDGE, CENTERL3,TOPEDGE},
698 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
699 		(1<<PORTNETSH)|OUTPORT, CENTERR4H, CENTER, CENTERR4H, CENTER},
700 	{sch_pc_either, x_("yt"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
701 		(2<<PORTNETSH)|OUTPORT, CENTERR2+D13, CENTERU2, CENTERR2+D13, CENTERU2},
702 	{sch_pc_either, x_("yc"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
703 		(3<<PORTNETSH)|OUTPORT, CENTERR2+D13, CENTERD2, CENTERR2+D13, CENTERD2}};
704 static TECH_POLYGON sch_xor_l[] = {					/* layers */
705 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_orl},
706 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_ort},
707 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_orb},
708 	{LNODE, 0, 3, CIRCLEARC, POINTS, sch_g_xor},
709 	{LNODE, 0, 8, VECTORS,   POINTS, sch_g_or}};
710 static TECH_NODES sch_xor = {
711 	x_("Xor"), NXOR, NONODEPROTO,					/* name */
712 	K10,K6,											/* size */
713 	4,sch_xor_p,									/* ports */
714 	5,sch_xor_l,									/* layers */
715 	(NPGATEXOR<<NFUNCTIONSH),						/* userbits */
716 	0,0,0,0,0,0,0,0,0};								/* characteristics */
717 
718 /* general flip flop */
719 static TECH_PORTS sch_ff_p[] = {					/* ports */
720 	{sch_pc_wire, x_("i1"), NOPORTPROTO, (180<<PORTANGLESH)|(45<<PORTARANGESH)|
721 		(0<<PORTNETSH)|INPORT,  LEFTEDGE, TOPBYP6, LEFTEDGE, TOPBYP6},
722 	{sch_pc_wire, x_("i2"), NOPORTPROTO, (180<<PORTANGLESH)|(45<<PORTARANGESH)|
723 		(1<<PORTNETSH)|INPORT,  LEFTEDGE, BOTBYP6, LEFTEDGE, BOTBYP6},
724 	{sch_pc_wire, x_("q"), NOPORTPROTO, (0<<PORTANGLESH)|(45<<PORTARANGESH)|
725 		(2<<PORTNETSH)|OUTPORT, RIGHTEDGE, TOPBYP6, RIGHTEDGE, TOPBYP6},
726 	{sch_pc_wire, x_("qb"), NOPORTPROTO, (0<<PORTANGLESH)|(45<<PORTARANGESH)|
727 		(3<<PORTNETSH)|OUTPORT, RIGHTEDGE, BOTBYP6, RIGHTEDGE, BOTBYP6},
728 	{sch_pc_wire, x_("ck"), NOPORTPROTO, (180<<PORTANGLESH)|(45<<PORTARANGESH)|
729 		(4<<PORTNETSH)|INPORT,  LEFTEDGE, CENTER, LEFTEDGE, CENTER},
730 	{sch_pc_wire, x_("preset"), NOPORTPROTO, (90<<PORTANGLESH)|(45<<PORTARANGESH)|
731 		(5<<PORTNETSH)|INPORT,  CENTER, TOPEDGE, CENTER, TOPEDGE},
732 	{sch_pc_wire, x_("clear"), NOPORTPROTO,(270<<PORTANGLESH)|(45<<PORTARANGESH)|
733 		(6<<PORTNETSH)|INPORT,  CENTER, BOTEDGE, CENTER, BOTEDGE}};
734 static TECH_POLYGON sch_ffp_l[] = {					/* layers */
735 	{LNODE, 0,                4, CLOSEDRECT, BOX,    sch_g_ffbox},
736 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextd},
737 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftexte},
738 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextq},
739 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextqb},
740 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextpr},
741 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextclr},
742 	{LNODE, 0,                3, OPENED,     POINTS, sch_g_ffarrow},
743 	{LNODE, 0,                4, OPENED,     POINTS, sch_g_ffp}};
744 static TECH_POLYGON sch_ffn_l[] = {					/* layers */
745 	{LNODE, 0,                4, CLOSEDRECT, BOX,    sch_g_ffbox},
746 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextd},
747 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftexte},
748 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextq},
749 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextqb},
750 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextpr},
751 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextclr},
752 	{LNODE, 0,                3, OPENED,     POINTS, sch_g_ffarrow},
753 	{LNODE, 0,                4, OPENED,     POINTS, sch_g_ffn}};
754 static TECH_POLYGON sch_ffms_l[] = {				/* layers */
755 	{LNODE, 0,                4, CLOSEDRECT, BOX,    sch_g_ffbox},
756 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextd},
757 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftexte},
758 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextq},
759 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextqb},
760 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextpr},
761 	{LTEXT, TXTSETQLAMBDA(4), 4, TEXTBOX,    POINTS, (INTBIG *)sch_g_fftextclr},
762 	{LNODE, 0,                3, OPENED,     POINTS, sch_g_ffarrow},
763 	{LNODE, 0,                6, OPENED,     POINTS, sch_g_ffms}};
764 static TECH_NODES sch_ff = {
765 	x_("Flip-Flop"), NFF, NONODEPROTO,				/* name */
766 	K6,K10,											/* size */
767 	7,sch_ff_p,										/* ports */
768 	9,sch_ffp_l,									/* layers */
769 	(NPFLIPFLOP<<NFUNCTIONSH),						/* userbits */
770 	0,0,0,0,0,0,0,0,0};								/* characteristics */
771 
772 /* general MUX */
773 static TECH_PORTS sch_mux_p[] = {					/* ports */
774 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(0<<PORTARANGESH)|
775 		(0<<PORTNETSH)|INPORT|PORTISOLATED, LEFTBYP8,BOTEDGE,LEFTBYP8,TOPEDGE},
776 	{sch_pc_bus, x_("s"), NOPORTPROTO, (270<<PORTANGLESH)|(0<<PORTARANGESH)|
777 		(2<<PORTNETSH)|INPORT, CENTER, BOTBYP875, CENTER, BOTBYP875},
778 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(0<<PORTARANGESH)|
779 		(1<<PORTNETSH)|OUTPORT, RIGHTBYP8, CENTER, RIGHTBYP8, CENTER}};
780 	static TECH_POLYGON sch_mux_l[] = {					/* layers */
781 	{LNODE, 0, 4, CLOSED,     POINTS, sch_g_mux}};
782 static TECH_NODES sch_mux = {
783 	x_("Mux"), NMUX, NONODEPROTO,					/* name */
784 	K8,K10,											/* size */
785 	3,sch_mux_p,									/* ports */
786 	1,sch_mux_l,									/* layers */
787 	(NPMUX<<NFUNCTIONSH),							/* userbits */
788 	0,0,0,0,0,0,0,0,0};								/* characteristics */
789 
790 /* black box */
791 static TECH_PORTS sch_bbox_p[] = {					/* ports */
792 	{sch_pc_either, x_("a"), NOPORTPROTO, (0<<PORTANGLESH)|(45<<PORTARANGESH)|
793 		(0<<PORTNETSH)|PORTISOLATED, RIGHTEDGE, BOTEDGE, RIGHTEDGE, TOPEDGE},
794 	{sch_pc_either, x_("b"), NOPORTPROTO, (90<<PORTANGLESH)|(45<<PORTARANGESH)|
795 		(1<<PORTNETSH)|PORTISOLATED, LEFTEDGE,  TOPEDGE, RIGHTEDGE, TOPEDGE},
796 	{sch_pc_either, x_("c"), NOPORTPROTO, (180<<PORTANGLESH)|(45<<PORTARANGESH)|
797 		(2<<PORTNETSH)|PORTISOLATED, LEFTEDGE,  BOTEDGE, LEFTEDGE,  TOPEDGE},
798 	{sch_pc_either, x_("d"), NOPORTPROTO, (270<<PORTANGLESH)|(45<<PORTARANGESH)|
799 		(3<<PORTNETSH)|PORTISOLATED, LEFTEDGE,  BOTEDGE, RIGHTEDGE, BOTEDGE}};
800 static TECH_POLYGON sch_bbox_l[] = {				/* layers */
801 	{LNODE, 0,         4, CLOSEDRECT, BOX,    sch_g_bbox}};
802 static TECH_NODES sch_bbox = {
803 	x_("Bbox"), NBBOX, NONODEPROTO,					/* name */
804 	K10,K10,										/* size */
805 	4,sch_bbox_p,									/* ports */
806 	1,sch_bbox_l,									/* layers */
807 	(NPUNKNOWN<<NFUNCTIONSH),						/* userbits */
808 	0,0,0,0,0,0,0,0,0};								/* characteristics */
809 
810 /* switch */
811 static TECH_PORTS sch_switch_p[] = {				/* ports */
812 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
813 		(0<<PORTNETSH)|PORTISOLATED, LEFTIN1, BOTIN1, LEFTIN1, TOPIN1},
814 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
815 		(1<<PORTNETSH), RIGHTIN1, CENTER, RIGHTIN1, CENTER}};
816 static TECH_POLYGON sch_switch_l[] = {				/* layers */
817 	{LNODE, 0, 2, DISC,       POINTS, sch_g_switchin},
818 	{LNODE, 0, 2, OPENED,     POINTS, sch_g_switchbar},
819 	{LNODE, 0, 2, DISC,       POINTS, sch_g_switchout}};
820 static TECH_NODES sch_switch = {
821 	x_("Switch"),NSWITCH,NONODEPROTO,				/* name */
822 	K6,K2,											/* size */
823 	2,sch_switch_p,									/* ports */
824 	3,sch_switch_l,									/* layers */
825 	(NPUNKNOWN<<NFUNCTIONSH),						/* userbits */
826 	0,0,0,0,0,0,0,0,0};								/* characteristics */
827 
828 /* off page connector */
829 static TECH_PORTS sch_offpage_p[] = {				/* ports */
830 	{sch_pc_either, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(45<<PORTARANGESH),
831 		LEFTEDGE,  CENTER, LEFTEDGE,  CENTER},
832 	{sch_pc_either, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(45<<PORTARANGESH),
833 		RIGHTEDGE, CENTER, RIGHTEDGE, CENTER}};
834 static TECH_POLYGON sch_offpage_l[] = {				/* layers */
835 	{LNODE, 0,         5, CLOSED,   POINTS, sch_g_offpage}};
836 static TECH_NODES sch_offpage = {
837 	x_("Off-Page"), NOFFPAGE, NONODEPROTO,			/* name */
838 	K4,K2,											/* size */
839 	2,sch_offpage_p,								/* ports */
840 	1,sch_offpage_l,								/* layers */
841 	(NPCONNECT<<NFUNCTIONSH),						/* userbits */
842 	0,0,0,0,0,0,0,0,0};								/* characteristics */
843 
844 /* power */
845 static TECH_PORTS sch_pwr_p[] = {					/* ports */
846 	{sch_pc_wire, x_("pwr"), NOPORTPROTO, (180<<PORTARANGESH)|PWRPORT,
847 		CENTER, CENTER, CENTER, CENTER}};
848 static TECH_POLYGON sch_pwr_l[] = {					/* layers */
849 	{LNODE, 0,        2, CIRCLE,   POINTS, sch_g_pwr1},
850 	{LNODE, 0,        2, CIRCLE,   POINTS, sch_g_pwr2}};
851 static TECH_NODES sch_pwr = {
852 	x_("Power"), NPWR, NONODEPROTO,					/* name */
853 	K3,K3,											/* size */
854 	1,sch_pwr_p,									/* ports */
855 	2,sch_pwr_l,									/* layers */
856 	(NPCONPOWER<<NFUNCTIONSH)|NSQUARE,				/* userbits */
857 	0,0,0,0,0,0,0,0,0};								/* characteristics */
858 
859 /* ground */
860 static TECH_PORTS sch_gnd_p[] = {					/* ports */
861 	{sch_pc_wire, x_("gnd"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH)|
862 		GNDPORT, CENTER, TOPEDGE, CENTER, TOPEDGE}};
863 static TECH_POLYGON sch_gnd_l[] = {					/* layers */
864 	{LNODE, 0, 12, VECTORS, POINTS, sch_g_gnd}};
865 static TECH_NODES sch_gnd = {
866 	x_("Ground"), NGND, NONODEPROTO,				/* name */
867 	K3,K4,											/* size */
868 	1,sch_gnd_p,									/* ports */
869 	1,sch_gnd_l,									/* layers */
870 	(NPCONGROUND<<NFUNCTIONSH),						/* userbits */
871 	0,0,0,0,0,0,0,0,0};								/* characteristics */
872 
873 /* source */
874 static TECH_PORTS sch_source_p[] = {				/* ports */
875 	{sch_pc_wire, x_("plus"),   NOPORTPROTO, (90<<PORTANGLESH)|(0<<PORTARANGESH)|
876 		(0<<PORTNETSH), CENTER, TOPEDGE, CENTER, TOPEDGE},
877 	{sch_pc_wire, x_("minus"),  NOPORTPROTO, (270<<PORTANGLESH)|(0<<PORTARANGESH)|
878 		(1<<PORTNETSH), CENTER, BOTEDGE, CENTER, BOTEDGE}};
879 static TECH_POLYGON sch_sourcev_l[] = {				/* layers */
880 	{LNODE, 0,                2, CIRCLE,   POINTS, sch_g_source},
881 	{LNODE, 0,                4, VECTORS,  POINTS, sch_g_sourcepl}};
882 static TECH_NODES sch_source = {
883 	x_("Source"), NSOURCE, NONODEPROTO,				/* name */
884 	K6,K6,											/* size */
885 	2,sch_source_p,									/* ports */
886 	2,sch_sourcev_l,								/* layers */
887 	(NPSOURCE<<NFUNCTIONSH)|NSQUARE,				/* userbits */
888 	0,0,0,0,0,0,0,0,0};								/* characteristics */
889 
890 /* transistor */
891 static TECH_PORTS sch_trans_p[] = {					/* ports */
892 	{sch_pc_wire, x_("g"), NOPORTPROTO, (180<<PORTARANGESH)|
893 		(0<<PORTNETSH)|INPORT, CENTER, TOPIN1, CENTER, TOPIN1},
894 	{sch_pc_wire, x_("s"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
895 		(1<<PORTNETSH)|BIDIRPORT, LEFTEDGE,  BOTEDGE,  LEFTEDGE,  BOTEDGE},
896 	{sch_pc_wire, x_("d"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
897 		(2<<PORTNETSH)|BIDIRPORT, RIGHTEDGE, BOTEDGE,  RIGHTEDGE, BOTEDGE}};
898 static TECH_POLYGON sch_nmos_l[] = {				/* layers */
899 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
900 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
901 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos}};
902 static TECH_POLYGON sch_pmos_l[] = {				/* layers */
903 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
904 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
905 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_pmos},
906 	{LNODE, 0,         2, CIRCLE,     POINTS, sch_g_pmoscir}};
907 static TECH_POLYGON sch_dmos_l[] = {				/* layers */
908 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
909 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
910 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
911 	{LNODE, 0,         4, FILLEDRECT, BOX,    sch_g_dmos}};
912 static TECH_POLYGON sch_npn_l[] = {					/* layers */
913 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_btran1},
914 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
915 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
916 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran2}};
917 static TECH_POLYGON sch_pnp_l[] = {					/* layers */
918 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_btran1},
919 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
920 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
921 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran3}};
922 static TECH_POLYGON sch_njfet_l[] = {				/* layers */
923 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
924 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
925 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
926 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran5}};
927 static TECH_POLYGON sch_pjfet_l[] = {				/* layers */
928 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
929 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
930 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
931 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran6}};
932 static TECH_POLYGON sch_dmes_l[] = {				/* layers */
933 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
934 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
935 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos}};
936 static TECH_POLYGON sch_emes_l[] = {				/* layers */
937 	{LNODE, 0,        14, VECTORS,    POINTS, sch_g_btran7},
938 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos}};
939 static TECH_NODES sch_trans = {
940 	x_("Transistor"), NTRANSISTOR, NONODEPROTO,		/* name */
941 	K4,K4,											/* size */
942 	3,sch_trans_p,									/* ports */
943 	3,sch_nmos_l,									/* layers */
944 	(NPTRANS<<NFUNCTIONSH),							/* userbits */
945 	0,0,0,0,0,0,0,0,0};								/* characteristics */
946 
947 /* resistor */
948 static TECH_PORTS sch_resist_p[] = {				/* ports */
949 	{sch_pc_wire, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
950 		(0<<PORTNETSH), LEFTBYP66,  CENTER, LEFTBYP66,  CENTER},
951 	{sch_pc_wire, x_("b"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
952 		(1<<PORTNETSH), RIGHTBYP66, CENTER, RIGHTBYP66, CENTER}};
953 	static TECH_POLYGON sch_resist_l[] = {			/* layers */
954 	{LNODE, 0,        10, OPENED,   POINTS, sch_g_resist}};
955 static TECH_NODES sch_resist = {
956 	x_("Resistor"), NRESISTOR, NONODEPROTO,			/* name */
957 	K6,K1,											/* size */
958 	2,sch_resist_p,									/* ports */
959 	1,sch_resist_l,									/* layers */
960 	(NPRESIST<<NFUNCTIONSH),						/* userbits */
961 	0,0,0,0,0,0,0,0,0};								/* characteristics */
962 
963 /* capacitor */
964 static TECH_PORTS sch_capac_p[] = {					/* ports */
965 	{sch_pc_wire, x_("a"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH)|
966 		(0<<PORTNETSH), CENTER, TOPEDGE, CENTER, TOPEDGE},
967 	{sch_pc_wire, x_("b"), NOPORTPROTO, (270<<PORTANGLESH)|(90<<PORTARANGESH)|
968 		(1<<PORTNETSH), CENTER, BOTEDGE,  CENTER, BOTEDGE}};
969 static TECH_POLYGON sch_capac_l[] = {				/* layers */
970 	{LNODE, 0,         8, VECTORS,  POINTS, sch_g_capac},
971 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_capace}};
972 static TECH_NODES sch_capac = {
973 	x_("Capacitor"), NCAPACITOR, NONODEPROTO,		/* name */
974 	K3,K4,											/* size */
975 	2,sch_capac_p,									/* ports */
976 	1,sch_capac_l,									/* layers */
977 	(NPCAPAC<<NFUNCTIONSH),							/* userbits */
978 	0,0,0,0,0,0,0,0,0};								/* characteristics */
979 
980 /* diode */
981 static TECH_PORTS sch_diode_p[] = {					/* ports */
982 	{sch_pc_wire, x_("a"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH)|
983 		(0<<PORTNETSH), CENTER, TOPEDGE, CENTER, TOPEDGE},
984 	{sch_pc_wire, x_("b"), NOPORTPROTO, (270<<PORTANGLESH)|(90<<PORTARANGESH)|
985 		(1<<PORTNETSH), CENTER, BOTEDGE,  CENTER, BOTEDGE}};
986 static TECH_POLYGON sch_diode_l[] = {				/* layers */
987 	{LNODE, 0,         6, VECTORS,  POINTS, sch_g_diode1},
988 	{LNODE, 0,         3, FILLED,   POINTS, sch_g_diode2}};
989 static TECH_NODES sch_diode = {
990 	x_("Diode"), NDIODE, NONODEPROTO,				/* name */
991 	K2,K4,											/* size */
992 	2,sch_diode_p,									/* ports */
993 	2,sch_diode_l,									/* layers */
994 	(NPDIODE<<NFUNCTIONSH),							/* userbits */
995 	0,0,0,0,0,0,0,0,0};								/* characteristics */
996 
997 /* inductor */
998 static TECH_PORTS sch_induct_p[] = {				/* ports */
999 	{sch_pc_wire, x_("a"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH)|
1000 		(0<<PORTNETSH), CENTER, TOPEDGE, CENTER, TOPEDGE},
1001 	{sch_pc_wire, x_("b"), NOPORTPROTO, (270<<PORTANGLESH)|(90<<PORTARANGESH)|
1002 		(1<<PORTNETSH), CENTER, BOTEDGE,  CENTER, BOTEDGE}};
1003 static TECH_POLYGON sch_induct_l[] = {				/* layers */
1004 	{LNODE, 0,         2, OPENED,   POINTS, sch_g_induct1},
1005 	{LNODE, 0,         2, CIRCLE,   POINTS, sch_g_induct2},
1006 	{LNODE, 0,         2, CIRCLE,   POINTS, sch_g_induct3},
1007 	{LNODE, 0,         2, CIRCLE,   POINTS, sch_g_induct4}};
1008 static TECH_NODES sch_induct = {
1009 	x_("Inductor"), NINDUCTOR, NONODEPROTO,			/* name */
1010 	K2,K4,											/* size */
1011 	2,sch_induct_p,									/* ports */
1012 	4,sch_induct_l,									/* layers */
1013 	(NPINDUCT<<NFUNCTIONSH),						/* userbits */
1014 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1015 
1016 /* meter */
1017 static TECH_PORTS sch_meter_p[] = {					/* ports */
1018 	{sch_pc_wire, x_("a"),  NOPORTPROTO, (90<<PORTANGLESH)|(0<<PORTARANGESH)|
1019 		(0<<PORTNETSH), CENTER, TOPEDGE, CENTER, TOPEDGE},
1020 	{sch_pc_wire, x_("b"),  NOPORTPROTO, (270<<PORTANGLESH)|(0<<PORTARANGESH)|
1021 		(1<<PORTNETSH), CENTER, BOTEDGE, CENTER, BOTEDGE}};
1022 static TECH_POLYGON sch_meterv_l[] = {				/* layers */
1023 	{LNODE, 0,                2, CIRCLE,  POINTS, sch_g_meter},
1024 	{LTEXT, TXTSETQLAMBDA(8), 4, TEXTBOX, BOX,    (INTBIG *)sch_g_meterv}};
1025 static TECH_NODES sch_meter = {
1026 	x_("Meter"), NMETER, NONODEPROTO,				/* name */
1027 	K6,K6,											/* size */
1028 	2,sch_meter_p,									/* ports */
1029 	2,sch_meterv_l,									/* layers */
1030 	(NPMETER<<NFUNCTIONSH)|NSQUARE,					/* userbits */
1031 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1032 
1033 /* well contact */
1034 static TECH_PORTS sch_well_p[] = {				/* ports */
1035 	{sch_pc_wire, x_("well"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH),
1036 		CENTER, TOPEDGE, CENTER, TOPEDGE}};
1037 static TECH_POLYGON sch_well_l[] = {				/* layers */
1038 	{LNODE, 0, 4, VECTORS, POINTS, sch_g_well}};
1039 static TECH_NODES sch_well = {
1040 	x_("Well"), NWELL, NONODEPROTO,					/* name */
1041 	K4,K2,											/* size */
1042 	1,sch_well_p,									/* ports */
1043 	1,sch_well_l,									/* layers */
1044 	(NPWELL<<NFUNCTIONSH),							/* userbits */
1045 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1046 
1047 /* substrate contact */
1048 static TECH_PORTS sch_substrate_p[] = {				/* ports */
1049 	{sch_pc_wire, x_("substrate"), NOPORTPROTO, (90<<PORTANGLESH)|(90<<PORTARANGESH),
1050 		CENTER, TOPEDGE, CENTER, TOPEDGE}};
1051 static TECH_POLYGON sch_substrate_l[] = {			/* layers */
1052 	{LNODE, 0, 8, VECTORS, POINTS, sch_g_substrate}};
1053 static TECH_NODES sch_substrate = {
1054 	x_("Substrate"), NSUBSTRATE, NONODEPROTO,		/* name */
1055 	K3,K3,											/* size */
1056 	1,sch_substrate_p,								/* ports */
1057 	1,sch_substrate_l,								/* layers */
1058 	(NPSUBSTRATE<<NFUNCTIONSH),						/* userbits */
1059 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1060 
1061 /* two-port */
1062 static TECH_PORTS sch_twoport_p[] = {				/* ports */
1063 	{sch_pc_wire, x_("a"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
1064 		(0<<PORTNETSH), LEFTEDGE, TOPBYP66, LEFTEDGE, TOPBYP66},
1065 	{sch_pc_wire, x_("b"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
1066 		(1<<PORTNETSH), LEFTEDGE, BOTBYP66, LEFTEDGE, BOTBYP66},
1067 	{sch_pc_wire, x_("x"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
1068 		(2<<PORTNETSH), RIGHTEDGE, TOPBYP66, RIGHTEDGE, TOPBYP66},
1069 	{sch_pc_wire, x_("y"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
1070 		(3<<PORTNETSH), RIGHTEDGE, BOTBYP66, RIGHTEDGE, BOTBYP66}};
1071 static TECH_POLYGON sch_twoportg_l[] = {			/* layers */
1072 	{LNODE, 0,         4, CLOSEDRECT, BOX,  sch_g_twobox},
1073 	{LNODE, 0,         8, VECTORS,  POINTS, sch_g_twogwire},
1074 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl},
1075 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twourpl}};
1076 static TECH_POLYGON sch_twoportvcvs_l[] = {			/* layers */
1077 	{LNODE, 0,         4, CLOSEDRECT, BOX,  sch_g_twobox},
1078 	{LNODE, 0,        12, VECTORS,  POINTS, sch_g_twonormwire},
1079 	{LNODE, 0,         2, CIRCLE,   POINTS, sch_g_twovsc},
1080 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twourpl},
1081 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl}};
1082 static TECH_POLYGON sch_twoportvccs_l[] = {			/* layers */
1083 	{LNODE, 0,         4, CLOSEDRECT, BOX,  sch_g_twobox},
1084 	{LNODE, 0,        12, VECTORS,  POINTS, sch_g_twonormwire},
1085 	{LNODE, 0,         8, VECTORS,  POINTS, sch_g_twocswire},
1086 	{LNODE, 0,         6, VECTORS,  POINTS, sch_g_twocsarr},
1087 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl}};
1088 static TECH_POLYGON sch_twoportccvs_l[] = {			/* layers */
1089 	{LNODE, 0,         4, CLOSEDRECT, BOX,  sch_g_twobox},
1090 	{LNODE, 0,         2, /*VECTORS*/OPENEDT1,  POINTS, sch_g_twoccwire},
1091 	{LNODE, 0,        12, VECTORS,  POINTS, sch_g_twonormwire},
1092 	{LNODE, 0,         2, CIRCLE,   POINTS, sch_g_twovsc},
1093 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twourpl},
1094 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl}};
1095 static TECH_POLYGON sch_twoportcccs_l[] = {			/* layers */
1096 	{LNODE, 0,         4, CLOSEDRECT, BOX,  sch_g_twobox},
1097 	{LNODE, 0,         2, /*VECTORS*/OPENEDT1,  POINTS, sch_g_twoccwire},
1098 	{LNODE, 0,        12, VECTORS,  POINTS, sch_g_twonormwire},
1099 	{LNODE, 0,         8, VECTORS,  POINTS, sch_g_twocswire},
1100 	{LNODE, 0,         6, VECTORS,  POINTS, sch_g_twocsarr},
1101 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl}};
1102 static TECH_POLYGON sch_twoporttran_l[] = {			/* layers */
1103 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twotrbox},
1104 	{LNODE, 0,         3, CIRCLEARC,POINTS, sch_g_twotr1},
1105 	{LNODE, 0,         3, CIRCLEARC,POINTS, sch_g_twotr2},
1106 	{LNODE, 0,         3, CIRCLEARC,POINTS, sch_g_twotr3},
1107 	{LNODE, 0,         8, VECTORS,  POINTS, sch_g_twotrwire},
1108 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twoulpl},
1109 	{LNODE, 0,         4, VECTORS,  POINTS, sch_g_twourrpl}};
1110 static TECH_NODES sch_twoport = {
1111 	x_("Two-Port"), NTWOPORT, NONODEPROTO,			/* name */
1112 	K10,K6,											/* size */
1113 	4,sch_twoport_p,								/* ports */
1114 	4,sch_twoportg_l,								/* layers */
1115 	(NPTLINE<<NFUNCTIONSH),							/* userbits */
1116 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1117 
1118 /* 4-port transistor */
1119 static TECH_PORTS sch_trans4_p[] = {				/* ports */
1120 	{sch_pc_wire, x_("g"), NOPORTPROTO, (180<<PORTARANGESH)|
1121 		(0<<PORTNETSH)|INPORT, CENTER, TOPIN1, CENTER, TOPIN1},
1122 	{sch_pc_wire, x_("s"), NOPORTPROTO, (180<<PORTANGLESH)|(90<<PORTARANGESH)|
1123 		(1<<PORTNETSH)|BIDIRPORT, LEFTEDGE,  BOTEDGE,  LEFTEDGE,  BOTEDGE},
1124 	{sch_pc_wire, x_("d"), NOPORTPROTO, (0<<PORTANGLESH)|(90<<PORTARANGESH)|
1125 		(2<<PORTNETSH)|BIDIRPORT, RIGHTEDGE, BOTEDGE,  RIGHTEDGE, BOTEDGE},
1126 	{sch_pc_wire, x_("b"), NOPORTPROTO, (270<<PORTANGLESH)|(90<<PORTARANGESH)|
1127 		(3<<PORTNETSH)|BIDIRPORT, LEFTBYP5, BOTEDGE,  LEFTBYP5, BOTEDGE}};
1128 static TECH_POLYGON sch_nmos4_l[] = {				/* layers */
1129 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
1130 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1131 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1132 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_nmos4}};
1133 static TECH_POLYGON sch_pmos4_l[] = {				/* layers */
1134 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
1135 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1136 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_pmos},
1137 	{LNODE, 0,         2, CIRCLE,     POINTS, sch_g_pmoscir},
1138 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_pmos4}};
1139 static TECH_POLYGON sch_dmos4_l[] = {				/* layers */
1140 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_mos},
1141 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1142 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1143 	{LNODE, 0,         4, FILLEDRECT, BOX,    sch_g_dmos},
1144 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_dmos4}};
1145 static TECH_POLYGON sch_npn4_l[] = {				/* layers */
1146 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_btran1},
1147 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1148 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1149 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran2},
1150 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_bip4}};
1151 static TECH_POLYGON sch_pnp4_l[] = {				/* layers */
1152 	{LNODE, 0,         6, OPENED,     POINTS, sch_g_btran1},
1153 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1154 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1155 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran3},
1156 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_bip4}};
1157 static TECH_POLYGON sch_njfet4_l[] = {				/* layers */
1158 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
1159 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1160 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1161 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran5},
1162 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_pmes4}};
1163 static TECH_POLYGON sch_pjfet4_l[] = {				/* layers */
1164 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
1165 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1166 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1167 	{LNODE, 0,         3, OPENED,     POINTS, sch_g_btran6},
1168 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_nmes4}};
1169 static TECH_POLYGON sch_dmes4_l[] = {				/* layers */
1170 	{LNODE, 0,        10, VECTORS,    POINTS, sch_g_btran4},
1171 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_trantop},
1172 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1173 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_nmes4}};
1174 static TECH_POLYGON sch_emes4_l[] = {				/* layers */
1175 	{LNODE, 0,        14, VECTORS,    POINTS, sch_g_btran7},
1176 	{LNODE, 0,         2, OPENED,     POINTS, sch_g_nmos},
1177 	{LNODE, 0,         6, VECTORS,    POINTS, sch_g_nmes4}};
1178 static TECH_NODES sch_trans4 = {
1179 	x_("4-Port-Transistor"), NTRANSISTOR4, NONODEPROTO,	/* name */
1180 	K4,K4,											/* size */
1181 	4,sch_trans4_p,									/* ports */
1182 	3,sch_nmos4_l,									/* layers */
1183 	(NPTRANS4<<NFUNCTIONSH),						/* userbits */
1184 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1185 
1186 /* global signal */
1187 static TECH_PORTS sch_globalsig_p[] = {				/* ports */
1188 	{sch_pc_wire, x_("global"), NOPORTPROTO, (270<<PORTANGLESH)|(90<<PORTARANGESH),
1189 		CENTER, BOTEDGE, CENTER, BOTEDGE}};
1190 static TECH_POLYGON sch_globalsig_l[] = {			/* layers */
1191 	{LNODE, 0, 4, CLOSED, POINTS, sch_g_global1},
1192 	{LNODE, 0, 4, CLOSED, POINTS, sch_g_global2}};
1193 static TECH_NODES sch_globalsig = {
1194 	x_("Global-Signal"), NGLOBALSIG, NONODEPROTO,	/* name */
1195 	K3,K3,											/* size */
1196 	1,sch_globalsig_p,								/* ports */
1197 	2,sch_globalsig_l,								/* layers */
1198 	(NPCONNECT<<NFUNCTIONSH),						/* userbits */
1199 	0,0,0,0,0,0,0,0,0};								/* characteristics */
1200 
1201 TECH_NODES *sch_nodeprotos[NODEPROTOCOUNT+1] = {
1202 	&sch_wirepin,  &sch_buspin,   &sch_wirecon,					/* pins */
1203 	&sch_buf,      &sch_and,      &sch_or,       &sch_xor,		/* gates: buffer, and, or, xor */
1204 	&sch_ff,       &sch_mux,									/* flipflop, mux */
1205 	&sch_bbox,     &sch_switch,									/* box/switch */
1206 	&sch_offpage,												/* offpage */
1207 	&sch_pwr,      &sch_gnd,      &sch_source,					/* pwr/gnd/source */
1208 	&sch_trans,    &sch_resist,   &sch_capac,					/* trans/resist/capac */
1209 	&sch_diode,    &sch_induct,									/* diode/inductor */
1210 	&sch_meter,													/* meter */
1211 	&sch_well,     &sch_substrate,								/* well/substrate */
1212 	&sch_twoport,  &sch_trans4,  &sch_globalsig,				/* twoport/4-port/global */
1213 	((TECH_NODES *)-1)
1214 };
1215 
1216 static INTBIG sch_node_widoff[NODEPROTOCOUNT*4] = {
1217 	  0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0, 0,					/* pins */
1218 	  0,K1, 0, 0,    0,H0, 0, 0,   K1,H0, 0, 0,    0,H0, 0, 0,	/* gates: buffer, and, or, xor */
1219 	  0, 0, 0, 0,    0, 0, 0, 0,								/* flipflop, mux */
1220 	  0, 0, 0, 0,    0, 0, 0, 0,								/* box/switch */
1221 	  0, 0, 0, 0,												/* offpage */
1222 	  0, 0, 0, 0,    0, 0, 0, 0,    0, 0, 0, 0,					/* pwr/gnd/source */
1223 	  0, 0, 0,K1,    0, 0, 0, 0,    0, 0, 0, 0,					/* trans/resist/capac */
1224 	  0, 0, 0, 0,    0, 0, 0, 0,								/* diode/inductor */
1225 	  0, 0, 0, 0,												/* meter */
1226 	  0, 0, 0, 0,    0, 0, 0, 0,								/* well/substrate */
1227 	  0, 0, 0, 0,    0, 0, 0,K1,    0, 0, 0, 0					/* twoport/4-port/global */
1228 };
1229 
1230 static CHAR *sch_node_vhdlstring[NODEPROTOCOUNT] = {
1231 	x_(""), x_(""), x_(""),										/* pins */
1232 	x_("buffer/inverter"), x_("and%ld/nand%ld"), x_("or%ld/nor%ld"), x_("xor%ld/xnor%ld"),	/* gates */
1233 	x_("ff"), x_("mux%ld"),										/* flipflop, mux */
1234 	x_(""), x_(""),												/* box/switch */
1235 	x_(""),														/* offpage */
1236 	x_(""), x_(""), x_(""),										/* pwr/gnd/source */
1237 	x_(""), x_(""), x_(""),										/* trans/resist/capac */
1238 	x_(""), x_(""),												/* diode/inductor */
1239 	x_(""),														/* meter */
1240 	x_(""), x_(""),												/* well/substrate */
1241 	x_(""), x_(""), x_("")										/* twoport/4-port/global */
1242 };
1243 
1244 /******************** VARIABLE AGGREGATION ********************/
1245 
1246 TECH_VARIABLES sch_variables[] =
1247 {
1248 	/* set general information about the technology */
1249 	{x_("TECH_layer_names"), (CHAR *)sch_layer_names, 0.0,
1250 		VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
1251 	{x_("TECH_layer_function"), (CHAR *)sch_layer_function, 0.0,
1252 		VINTEGER|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
1253 	{x_("TECH_node_width_offset"), (CHAR *)sch_node_widoff, 0.0,
1254 		VFRACT|VDONTSAVE|VISARRAY|((NODEPROTOCOUNT*4)<<VLENGTHSH)},
1255 	{x_("TECH_vhdl_names"), (CHAR *)sch_node_vhdlstring, 0.0,
1256 		VSTRING|VDONTSAVE|VISARRAY|(NODEPROTOCOUNT<<VLENGTHSH)},
1257 
1258 	/* set information for the USER analysis tool */
1259 	{x_("USER_layer_letters"), (CHAR *)sch_layer_letters, 0.0,
1260 		VSTRING|VDONTSAVE|VISARRAY|(MAXLAYERS<<VLENGTHSH)},
1261 	{NULL, NULL, 0.0, 0}
1262 };
1263 
1264 /******************** ROUTINES ********************/
1265 
sch_initprocess(TECHNOLOGY * tech,INTBIG pass)1266 BOOLEAN sch_initprocess(TECHNOLOGY *tech, INTBIG pass)
1267 {
1268 	switch (pass)
1269 	{
1270 		case 0:
1271 			/* initialize the technology variable */
1272 			sch_tech = tech;
1273 			break;
1274 
1275 		case 1:
1276 			/* cache pointers to the primitives */
1277 			sch_wirepinprim = getnodeproto(x_("schematic:Wire_Pin"));
1278 			sch_buspinprim = getnodeproto(x_("schematic:Bus_Pin"));
1279 			sch_wireconprim = getnodeproto(x_("schematic:Wire_Con"));
1280 			sch_bufprim = getnodeproto(x_("schematic:Buffer"));
1281 			sch_andprim = getnodeproto(x_("schematic:And"));
1282 			sch_orprim = getnodeproto(x_("schematic:Or"));
1283 			sch_xorprim = getnodeproto(x_("schematic:Xor"));
1284 			sch_ffprim = getnodeproto(x_("schematic:Flip-Flop"));
1285 			sch_muxprim = getnodeproto(x_("schematic:Mux"));
1286 			sch_bboxprim = getnodeproto(x_("schematic:Bbox"));
1287 			sch_switchprim = getnodeproto(x_("schematic:Switch"));
1288 			sch_offpageprim = getnodeproto(x_("schematic:Off-Page"));
1289 			sch_pwrprim = getnodeproto(x_("schematic:Power"));
1290 			sch_gndprim = getnodeproto(x_("schematic:Ground"));
1291 			sch_sourceprim = getnodeproto(x_("schematic:Source"));
1292 			sch_transistorprim = getnodeproto(x_("schematic:Transistor"));
1293 			sch_resistorprim = getnodeproto(x_("schematic:Resistor"));
1294 			sch_capacitorprim = getnodeproto(x_("schematic:Capacitor"));
1295 			sch_diodeprim = getnodeproto(x_("schematic:Diode"));
1296 			sch_inductorprim = getnodeproto(x_("schematic:Inductor"));
1297 			sch_meterprim = getnodeproto(x_("schematic:Meter"));
1298 			sch_wellprim = getnodeproto(x_("schematic:Well"));
1299 			sch_substrateprim = getnodeproto(x_("schematic:Substrate"));
1300 			sch_twoportprim = getnodeproto(x_("schematic:Two-Port"));
1301 			sch_transistor4prim = getnodeproto(x_("schematic:4-Port-Transistor"));
1302 			sch_globalprim = getnodeproto(x_("schematic:Global-Signal"));
1303 
1304 			sch_wirearc = getarcproto(x_("schematic:wire"));
1305 			sch_busarc = getarcproto(x_("schematic:bus"));
1306 
1307 			sch_meterkey = makekey(x_("SCHEM_meter_type"));
1308 			sch_diodekey = makekey(x_("SCHEM_diode"));
1309 			sch_capacitancekey = makekey(x_("SCHEM_capacitance"));
1310 			sch_resistancekey = makekey(x_("SCHEM_resistance"));
1311 			sch_inductancekey = makekey(x_("SCHEM_inductance"));
1312 			sch_functionkey = makekey(x_("SCHEM_function"));
1313 			sch_spicemodelkey = makekey(x_("SIM_spice_model"));
1314 			sch_globalnamekey = makekey(x_("SCHEM_global_name"));
1315 
1316 			/* differential ports are enabled */
1317 			sch_anddiffports = sch_ordiffports = sch_xordiffports = NOPORTPROTO;
1318 
1319 			/* translate strings on schematic nodes */
1320 			sch_g_fftextclr[16] = _("CLR");
1321 			sch_wirepinsizex = sch_wirepinprim->highx - sch_wirepinprim->lowx;
1322 			sch_wirepinsizey = sch_wirepinprim->highy - sch_wirepinprim->lowy;
1323 			break;
1324 
1325 		case 2:
1326 			/* set the default transistor placement to be rotated */
1327 			nextchangequiet();
1328 			setvalkey((INTBIG)sch_transistorprim, VNODEPROTO, us_placement_angle_key, 900, VINTEGER|VDONTSAVE);
1329 			nextchangequiet();
1330 			setvalkey((INTBIG)sch_transistor4prim, VNODEPROTO, us_placement_angle_key, 900, VINTEGER|VDONTSAVE);
1331 			break;
1332 	}
1333 	return(FALSE);
1334 }
1335 
sch_termprocess(void)1336 void sch_termprocess(void)
1337 {
1338 	/* put all ports into play so that deallocation will be complete */
1339 	if (sch_anddiffports == NOPORTPROTO) return;
1340 	sch_andprim->firstportproto->nextportproto->nextportproto = sch_anddiffports;
1341 	sch_orprim->firstportproto->nextportproto->nextportproto = sch_ordiffports;
1342 	sch_xorprim->firstportproto->nextportproto->nextportproto = sch_xordiffports;
1343 	sch_anddiffports = sch_ordiffports = sch_xordiffports = NOPORTPROTO;
1344 }
1345 
sch_setmode(INTBIG count,CHAR * par[])1346 void sch_setmode(INTBIG count, CHAR *par[])
1347 {
1348 	REGISTER CHAR *pp;
1349 	REGISTER INTBIG l;
1350 
1351 	if (count == 0)
1352 	{
1353 		/* report size of negating bubbles */
1354 		ttyputmsg(M_("Diameter of negating bubbles is %s"), frtoa(sch_bubblediameter));
1355 		return;
1356 	}
1357 
1358 	l = estrlen(pp = par[0]);
1359 	if (namesamen(pp, x_("negating-bubble-diameter"), l) == 0)
1360 	{
1361 		/* get new negating bubble diameter */
1362 		if (count <= 1)
1363 		{
1364 			ttyputmsg(M_("Diameter of negating bubbles is %s"), frtoa(sch_bubblediameter));
1365 			return;
1366 		}
1367 		l = atofr(par[1]);
1368 		if (l > 0) sch_bubblediameter = l; else
1369 			ttyputerr(M_("Bubble diameter must be positive and nonzero"));
1370 		return;
1371 	}
1372 	if (namesamen(pp, x_("disable-differential-ports"), l) == 0)
1373 	{
1374 		if (sch_anddiffports != NOPORTPROTO)
1375 		{
1376 			ttyputerr(M_("Differential ports are already disabled"));
1377 			return;
1378 		}
1379 		sch_anddiffports = sch_andprim->firstportproto->nextportproto->nextportproto;
1380 		sch_andprim->firstportproto->nextportproto->nextportproto = NOPORTPROTO;
1381 
1382 		sch_ordiffports = sch_orprim->firstportproto->nextportproto->nextportproto;
1383 		sch_orprim->firstportproto->nextportproto->nextportproto = NOPORTPROTO;
1384 
1385 		sch_xordiffports = sch_xorprim->firstportproto->nextportproto->nextportproto;
1386 		sch_xorprim->firstportproto->nextportproto->nextportproto = NOPORTPROTO;
1387 		net_redoprim();
1388 		return;
1389 	}
1390 	if (namesamen(pp, x_("enable-differential-ports"), l) == 0)
1391 	{
1392 		if (sch_anddiffports == NOPORTPROTO)
1393 		{
1394 			ttyputerr(M_("Differential ports are already enabled"));
1395 			return;
1396 		}
1397 		sch_andprim->firstportproto->nextportproto->nextportproto = sch_anddiffports;
1398 		sch_orprim->firstportproto->nextportproto->nextportproto = sch_ordiffports;
1399 		sch_xorprim->firstportproto->nextportproto->nextportproto = sch_xordiffports;
1400 		sch_anddiffports = sch_ordiffports = sch_xordiffports = NOPORTPROTO;
1401 		net_redoprim();
1402 		return;
1403 	}
1404 	ttyputbadusage(x_("technology tell schematic"));
1405 }
1406 
sch_request(CHAR * command,va_list ap)1407 INTBIG sch_request(CHAR *command, va_list ap)
1408 {
1409 	REGISTER PORTPROTO *pp;
1410 
1411 	if (namesame(command, x_("ignoring-resistor-topology")) == 0)
1412 	{
1413 		pp = sch_resistorprim->firstportproto->nextportproto;
1414 		if ((pp->userbits&PORTNET) == 0) return(1);
1415 		return(0);
1416 	}
1417 	if (namesame(command, x_("ignore-resistor-topology")) == 0)
1418 	{
1419 		pp = sch_resistorprim->firstportproto->nextportproto;
1420 		pp->userbits = (pp->userbits & ~PORTNET);
1421 		net_redoprim();
1422 		return(0);
1423 	}
1424 	if (namesame(command, x_("include-resistor-topology")) == 0)
1425 	{
1426 		pp = sch_resistorprim->firstportproto->nextportproto;
1427 		pp->userbits = (pp->userbits & ~PORTNET) | (1 << PORTNETSH);
1428 		net_redoprim();
1429 		return(0);
1430 	}
1431 
1432 	if (namesame(command, x_("get-bubble-size")) == 0)
1433 	{
1434 		return(sch_bubblediameter);
1435 	}
1436 	if (namesame(command, x_("set-bubble-size")) == 0)
1437 	{
1438 		sch_bubblediameter = va_arg(ap, INTBIG);
1439 		return(0);
1440 	}
1441 	return(0);
1442 }
1443 
sch_nodepolys(NODEINST * ni,INTBIG * reasonable,WINDOWPART * win)1444 INTBIG sch_nodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win)
1445 {
1446 	return(sch_intnodepolys(ni, reasonable, win, &tech_oneprocpolyloop, &sch_oneprocpolyloop));
1447 }
1448 
sch_intnodepolys(NODEINST * ni,INTBIG * reasonable,WINDOWPART * win,POLYLOOP * pl,SCHPOLYLOOP * schpl)1449 INTBIG sch_intnodepolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win, POLYLOOP *pl, SCHPOLYLOOP *schpl)
1450 {
1451 	REGISTER INTBIG total, pindex, buscon, nonbuscon, hei, arcs, i, implicitcon;
1452 	INTBIG depth;
1453 	NODEINST **nilist, *upni;
1454 	REGISTER PORTARCINST *pi;
1455 	REGISTER PORTEXPINST *pe;
1456 	REGISTER PORTPROTO *pp;
1457 
1458 	/* get the default number of polygons and list of layers */
1459 	pindex = ni->proto->primindex;
1460 	total = sch_nodeprotos[pindex-1]->layercount;
1461 	schpl->layerlist = sch_nodeprotos[pindex-1]->layerlist;
1462 
1463 	/* special cases for special primitives */
1464 	switch (pindex)
1465 	{
1466 		case NWIREPIN:	/* wire pins disappear with one or two wires */
1467 			if (tech_pinusecount(ni, win)) total = 0;
1468 			break;
1469 
1470 		case NBUSPIN:	/* bus pins get bigger in "T" configurations, disappear when alone and exported */
1471 			buscon = nonbuscon = 0;
1472 			for (pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1473 			{
1474 				if (pi->conarcinst->proto == sch_busarc) buscon++; else
1475 					nonbuscon++;
1476 			}
1477 			if (buscon == 0 && nonbuscon == 0) implicitcon = 1; else
1478 				implicitcon = 0;
1479 
1480 			/* if the next level up the hierarchy is visible, consider arcs connected there */
1481 			if (win != NOWINDOWPART && ni->firstportexpinst != NOPORTEXPINST)
1482 			{
1483 				db_gettraversalpath(ni->parent, NOWINDOWPART, &nilist, &depth);
1484 				if (depth == 1)
1485 				{
1486 					upni = nilist[0];
1487 					if (upni->proto == ni->parent && upni->parent == win->curnodeproto)
1488 					{
1489 						for(pe = ni->firstportexpinst; pe != NOPORTEXPINST; pe = pe->nextportexpinst)
1490 						{
1491 							for (pi = upni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1492 							{
1493 								if (pi->proto != pe->exportproto) continue;
1494 								if (pi->conarcinst->proto == sch_busarc) buscon++; else
1495 									nonbuscon++;
1496 							}
1497 						}
1498 					}
1499 				}
1500 			}
1501 
1502 			/* bus pins don't show wire pin in center if not tapped */
1503 			if (nonbuscon == 0) total--;
1504 
1505 			schpl->buspinlayer = LBUS;
1506 			schpl->buspinpoints = sch_g_buspindisc;
1507 			if (buscon+implicitcon > 2)
1508 			{
1509 				/* larger pin because it is connected to 3 or more bus arcs */
1510 				schpl->buspinsize = H0;
1511 			} else
1512 			{
1513 				/* smaller pin because it has 0, 1, or 2 connections */
1514 				schpl->buspinsize = Q0;
1515 				if (buscon == 0)
1516 				{
1517 					if (nonbuscon+implicitcon > 2)
1518 					{
1519 						schpl->buspinlayer = LARC;
1520 						schpl->buspinpoints = sch_g_bustapdisc;
1521 						total--;
1522 					} else
1523 					{
1524 						if (ni->firstportexpinst != NOPORTEXPINST)
1525 							total = 0;
1526 					}
1527 				}
1528 			}
1529 			break;
1530 
1531 		case NFF:	/* determine graphics to use for FlipFlops */
1532 			switch (ni->userbits&FFCLOCK)
1533 			{
1534 				case FFCLOCKMS:		/* FlipFlop is Master/slave */
1535 					schpl->layerlist = sch_ffms_l;
1536 					break;
1537 				case FFCLOCKP:		/* FlipFlop is Positive clock */
1538 					schpl->layerlist = sch_ffp_l;
1539 					break;
1540 				case FFCLOCKN:		/* FlipFlop is Negative clock */
1541 					schpl->layerlist = sch_ffn_l;
1542 					break;
1543 			}
1544 			break;
1545 
1546 		case NSWITCH:	/* add in multiple connection sites for switch */
1547 			hei = (ni->highy - ni->lowy) / lambdaofnode(ni);
1548 			if (hei >= 4) total += (hei/2)-1;
1549 			if (((hei/2)&1) == 0) schpl->switchbarvalue = 0; else
1550 				schpl->switchbarvalue = K1;
1551 			break;
1552 
1553 		case NTRANSISTOR:	/* determine graphics to use for transistors */
1554 			switch (ni->userbits&NTECHBITS)
1555 			{
1556 				case TRANNMOS:				/* Transistor is N channel MOS */
1557 					schpl->layerlist = sch_nmos_l;
1558 					total = 3;
1559 					break;
1560 				case TRANDMOS:				/* Transistor is Depletion MOS */
1561 					schpl->layerlist = sch_dmos_l;
1562 					total = 4;
1563 					break;
1564 				case TRANPMOS:				/* Transistor is P channel MOS */
1565 					schpl->layerlist = sch_pmos_l;
1566 					total = 4;
1567 					break;
1568 				case TRANNPN:				/* Transistor is NPN Junction */
1569 					schpl->layerlist = sch_npn_l;
1570 					total = 4;
1571 					break;
1572 				case TRANPNP:				/* Transistor is PNP Junction */
1573 					schpl->layerlist = sch_pnp_l;
1574 					total = 4;
1575 					break;
1576 				case TRANNJFET:				/* Transistor is N Channel Junction FET */
1577 					schpl->layerlist = sch_njfet_l;
1578 					total = 4;
1579 					break;
1580 				case TRANPJFET:				/* Transistor is P Channel Junction FET */
1581 					schpl->layerlist = sch_pjfet_l;
1582 					total = 4;
1583 					break;
1584 				case TRANDMES:				/* Transistor is Depletion MESFET */
1585 					schpl->layerlist = sch_dmes_l;
1586 					total = 3;
1587 					break;
1588 				case TRANEMES:				/* Transistor is Enhancement MESFET */
1589 					schpl->layerlist = sch_emes_l;
1590 					total = 2;
1591 					break;
1592 			}
1593 			break;
1594 
1595 		case NCAPACITOR:	/* determine graphics to use for capacitors */
1596 			if ((ni->userbits&NTECHBITS) == CAPACELEC)
1597 				total++;
1598 			break;
1599 
1600 		case NTWOPORT:	/* determine graphics to use for Two-Ports */
1601 			switch (ni->userbits&NTECHBITS)
1602 			{
1603 				case TWOPVCCS:					/* Two-port is Transconductance (VCCS) */
1604 					schpl->layerlist = sch_twoportvccs_l;
1605 					total = 5;
1606 					break;
1607 				case TWOPCCVS:					/* Two-port is Transresistance (CCVS) */
1608 					schpl->layerlist = sch_twoportccvs_l;
1609 					total = 6;
1610 					break;
1611 				case TWOPVCVS:					/* Two-port is Voltage gain (VCVS) */
1612 					schpl->layerlist = sch_twoportvcvs_l;
1613 					total = 5;
1614 					break;
1615 				case TWOPCCCS:					/* Two-port is Current gain (CCCS) */
1616 					schpl->layerlist = sch_twoportcccs_l;
1617 					total = 6;
1618 					break;
1619 				case TWOPTLINE:					/* Two-port is Transmission Line */
1620 					schpl->layerlist = sch_twoporttran_l;
1621 					total = 7;
1622 					break;
1623 			}
1624 			break;
1625 		case NTRANSISTOR4:	/* determine graphics to use for 4-port transistors */
1626 			switch (ni->userbits&NTECHBITS)
1627 			{
1628 				case TRANNMOS:				/* Transistor is N channel MOS */
1629 					schpl->layerlist = sch_nmos4_l;
1630 					total = 4;
1631 					break;
1632 				case TRANDMOS:				/* Transistor is Depletion MOS */
1633 					schpl->layerlist = sch_dmos4_l;
1634 					total = 5;
1635 					break;
1636 				case TRANPMOS:				/* Transistor is P channel MOS */
1637 					schpl->layerlist = sch_pmos4_l;
1638 					total = 5;
1639 					break;
1640 				case TRANNPN:				/* Transistor is NPN Junction */
1641 					schpl->layerlist = sch_npn4_l;
1642 					total = 5;
1643 					break;
1644 				case TRANPNP:				/* Transistor is PNP Junction */
1645 					schpl->layerlist = sch_pnp4_l;
1646 					total = 5;
1647 					break;
1648 				case TRANNJFET:				/* Transistor is N Channel Junction FET */
1649 					schpl->layerlist = sch_njfet4_l;
1650 					total = 5;
1651 					break;
1652 				case TRANPJFET:				/* Transistor is P Channel Junction FET */
1653 					schpl->layerlist = sch_pjfet4_l;
1654 					total = 5;
1655 					break;
1656 				case TRANDMES:				/* Transistor is Depletion MESFET */
1657 					schpl->layerlist = sch_dmes4_l;
1658 					total = 4;
1659 					break;
1660 				case TRANEMES:				/* Transistor is Enhancement MESFET */
1661 					schpl->layerlist = sch_emes4_l;
1662 					total = 3;
1663 					break;
1664 			}
1665 			break;
1666 	}
1667 
1668 	schpl->extrasteinerpoint = total;
1669 	switch (pindex)
1670 	{
1671 		case NSWITCH:
1672 		case NOFFPAGE:
1673 		case NPWR:
1674 		case NGND:
1675 		case NSOURCE:
1676 		case NTRANSISTOR:
1677 		case NRESISTOR:
1678 		case NCAPACITOR:
1679 		case NDIODE:
1680 		case NINDUCTOR:
1681 		case NMETER:
1682 		case NWELL:
1683 		case NSUBSTRATE:
1684 		case NTWOPORT:
1685 		case NTRANSISTOR4:
1686 			for(i=0; i<sch_nodeprotos[pindex-1]->portcount; i++)
1687 			{
1688 				pp = sch_nodeprotos[pindex-1]->portlist[i].addr;
1689 				arcs = 0;
1690 				for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1691 					if (pi->proto == pp) arcs++;
1692 				if (arcs > 1)
1693 				{
1694 					schpl->extrasteinerport[total - schpl->extrasteinerpoint] = &sch_nodeprotos[pindex-1]->portlist[i];
1695 					total++;
1696 				}
1697 			}
1698 			break;
1699 	}
1700 
1701 	/* add in displayable variables */
1702 	pl->realpolys = total;
1703 	total += tech_displayablenvars(ni, pl->curwindowpart, pl);
1704 	if (reasonable != 0) *reasonable = total;
1705 	return(total);
1706 }
1707 
sch_shapenodepoly(NODEINST * ni,INTBIG box,POLYGON * poly)1708 void sch_shapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly)
1709 {
1710 	sch_intshapenodepoly(ni, box, poly, &tech_oneprocpolyloop, &sch_oneprocpolyloop);
1711 }
1712 
sch_intshapenodepoly(NODEINST * ni,INTBIG box,POLYGON * poly,POLYLOOP * pl,SCHPOLYLOOP * schpl)1713 void sch_intshapenodepoly(NODEINST *ni, INTBIG box, POLYGON *poly, POLYLOOP *pl, SCHPOLYLOOP *schpl)
1714 {
1715 	REGISTER INTBIG lambda, width, height;
1716 	REGISTER VARIABLE *var;
1717 	REGISTER TECH_PORTS *tp;
1718 	REGISTER TECH_POLYGON *lay;
1719 
1720 	/* handle displayable variables */
1721 	if (box >= pl->realpolys)
1722 	{
1723 		var = tech_filldisplayablenvar(ni, poly, pl->curwindowpart, 0, pl);
1724 		return;
1725 	}
1726 
1727 	/* get the unit size (lambda) */
1728 	switch (ni->proto->primindex)
1729 	{
1730 #ifdef SCALABLEGATES
1731 		case NAND:
1732 			width = ni->highx - ni->lowx;
1733 			height = ni->highy - ni->lowy;
1734 			lambda = width / 8;
1735 			if (height < lambda * 6) lambda = height / 6;
1736 			break;
1737 		case NOR:
1738 		case NXOR:
1739 			width = ni->highx - ni->lowx;
1740 			height = ni->highy - ni->lowy;
1741 			lambda = width / 10;
1742 			if (height < lambda * 6) lambda = height / 6;
1743 			break;
1744 #endif
1745 		default:
1746 			lambda = lambdaofnode(ni);
1747 			break;
1748 	}
1749 
1750 	if (box >= schpl->extrasteinerpoint)
1751 	{
1752 		/* handle extra steiner points */
1753 		tp = schpl->extrasteinerport[box - schpl->extrasteinerpoint];
1754 		if (poly->limit < 2) (void)extendpolygon(poly, 2);
1755 		poly->xv[0] = (getrange(ni->lowx, ni->highx, tp->lowxmul, tp->lowxsum, lambda) +
1756 			getrange(ni->lowx, ni->highx, tp->highxmul, tp->highxsum, lambda)) / 2;
1757 		poly->yv[0] = (getrange(ni->lowy, ni->highy, tp->lowymul, tp->lowysum, lambda) +
1758 			getrange(ni->lowy, ni->highy, tp->highymul, tp->highysum, lambda)) / 2;
1759 		poly->xv[1] = poly->xv[0] + sch_wirepinsizex/2;
1760 		poly->yv[1] = poly->yv[0];
1761 		poly->count = 2;
1762 		poly->style = DISC;
1763 		poly->layer = LARC;
1764 		poly->tech = sch_tech;
1765 		poly->desc = sch_layers[poly->layer];
1766 		return;
1767 	}
1768 
1769 	/* handle extra blobs on tall switches */
1770 	lay = &schpl->layerlist[box];
1771 	switch (ni->proto->primindex)
1772 	{
1773 		case NBUSPIN:
1774 			if (box == 0)
1775 			{
1776 				sch_buspin_l[0].layernum = (INTSML)schpl->buspinlayer;
1777 				sch_buspin_l[0].points = schpl->buspinpoints;
1778 				sch_g_buspindisc[4] = schpl->buspinsize;
1779 			}
1780 			break;
1781 		case NSWITCH:
1782 			if (box >= 2)
1783 			{
1784 				sch_g_switchout[3] = sch_g_switchout[7] = WHOLE*2*(box-1) - WHOLE;
1785 				box = 2;
1786 				lay = &schpl->layerlist[box];
1787 			}
1788 			if (lay->points == sch_g_switchbar)
1789 				sch_g_switchbar[7] = schpl->switchbarvalue;
1790 			break;
1791 		case NFF:
1792 			if (lay->points == (INTBIG *)sch_g_fftextd)
1793 			{
1794 				switch (ni->userbits&FFTYPE)
1795 				{
1796 					case FFTYPERS: sch_g_fftextd[16] = sch_R;        break;
1797 					case FFTYPEJK: sch_g_fftextd[16] = sch_J;        break;
1798 					case FFTYPED:  sch_g_fftextd[16] = sch_D;        break;
1799 					case FFTYPET:  sch_g_fftextd[16] = sch_T;        break;
1800 				}
1801 			} else if (lay->points == (INTBIG *)sch_g_fftexte)
1802 			{
1803 				switch (ni->userbits&FFTYPE)
1804 				{
1805 					case FFTYPERS: sch_g_fftexte[16] = sch_S;        break;
1806 					case FFTYPEJK: sch_g_fftexte[16] = sch_K;        break;
1807 					case FFTYPED:  sch_g_fftexte[16] = sch_E;        break;
1808 					case FFTYPET:  sch_g_fftexte[16] = sch_NULLSTR;  break;
1809 				}
1810 			}
1811 			break;
1812 		case NDIODE:	/* determine graphics to use for diodes */
1813 			if (box == 0)
1814 			{
1815 				switch (ni->userbits&NTECHBITS)
1816 				{
1817 					case DIODENORM:					/* Diode is normal */
1818 						lay->points = sch_g_diode1;
1819 						lay->count = 6;
1820 						break;
1821 					case DIODEZENER:				/* Diode is Zener */
1822 						lay->points = sch_g_diode3;
1823 						lay->count = 10;
1824 						break;
1825 				}
1826 			}
1827 			break;
1828 	}
1829 
1830 	tech_fillpoly(poly, lay, ni, lambda, FILLED);
1831 	TDCLEAR(poly->textdescript);
1832 	TDSETSIZE(poly->textdescript, lay->portnum);
1833 	poly->tech = sch_tech;
1834 	poly->desc = sch_layers[poly->layer];
1835 }
1836 
sch_allnodepolys(NODEINST * ni,POLYLIST * plist,WINDOWPART * win,BOOLEAN onlyreasonable)1837 INTBIG sch_allnodepolys(NODEINST *ni, POLYLIST *plist, WINDOWPART *win, BOOLEAN onlyreasonable)
1838 {
1839 	REGISTER INTBIG tot, j;
1840 	INTBIG reasonable;
1841 	REGISTER NODEPROTO *np;
1842 	REGISTER POLYGON *poly;
1843 	POLYLOOP mypl;
1844 	SCHPOLYLOOP myschpl;
1845 
1846 	np = ni->proto;
1847 	mypl.curwindowpart = win;
1848 	tot = sch_intnodepolys(ni, &reasonable, win, &mypl, &myschpl);
1849 	if (onlyreasonable) tot = reasonable;
1850 	if (mypl.realpolys < tot) tot = mypl.realpolys;
1851 	if (ensurepolylist(plist, tot, db_cluster)) return(-1);
1852 	for(j = 0; j < tot; j++)
1853 	{
1854 		poly = plist->polygons[j];
1855 		poly->tech = sch_tech;
1856 		sch_intshapenodepoly(ni, j, poly, &mypl, &myschpl);
1857 	}
1858 	return(tot);
1859 }
1860 
sch_nodeEpolys(NODEINST * ni,INTBIG * reasonable,WINDOWPART * win)1861 INTBIG sch_nodeEpolys(NODEINST *ni, INTBIG *reasonable, WINDOWPART *win)
1862 {
1863 	Q_UNUSED( ni );
1864 	Q_UNUSED( win );
1865 
1866 	if (reasonable != 0) *reasonable = 0;
1867 	return(0);
1868 }
1869 
sch_shapeEnodepoly(NODEINST * ni,INTBIG box,POLYGON * poly)1870 void sch_shapeEnodepoly(NODEINST *ni, INTBIG box, POLYGON *poly)
1871 {
1872 	Q_UNUSED( ni );
1873 	Q_UNUSED( box );
1874 	Q_UNUSED( poly );
1875 }
1876 
sch_allnodeEpolys(NODEINST * ni,POLYLIST * plist,WINDOWPART * win,BOOLEAN onlyreasonable)1877 INTBIG sch_allnodeEpolys(NODEINST *ni, POLYLIST *plist, WINDOWPART *win, BOOLEAN onlyreasonable)
1878 {
1879 	Q_UNUSED( ni );
1880 	Q_UNUSED( plist );
1881 	Q_UNUSED( win );
1882 	Q_UNUSED( onlyreasonable );
1883 	return(0);
1884 }
1885 
sch_nodesizeoffset(NODEINST * ni,INTBIG * lx,INTBIG * ly,INTBIG * hx,INTBIG * hy)1886 void sch_nodesizeoffset(NODEINST *ni, INTBIG *lx, INTBIG *ly, INTBIG *hx, INTBIG *hy)
1887 {
1888 	REGISTER INTBIG index, width, height, unitsize;
1889 
1890 	index = ni->proto->primindex;
1891 	switch (index)
1892 	{
1893 #ifdef SCALABLEGATES
1894 		case NAND:
1895 			width = ni->highx - ni->lowx;
1896 			height = ni->highy - ni->lowy;
1897 			unitsize = width / 8;
1898 			if (height < unitsize * 6) unitsize = height / 6;
1899 			*lx = 0;
1900 			*hx = unitsize/2;
1901 			*ly = *hy = 0;
1902 			break;
1903 		case NOR:
1904 			width = ni->highx - ni->lowx;
1905 			height = ni->highy - ni->lowy;
1906 			unitsize = width / 10;
1907 			if (height < unitsize * 6) unitsize = height / 6;
1908 			*lx = unitsize;
1909 			*hx = unitsize/2;
1910 			*ly = *hy = 0;
1911 			break;
1912 		case NXOR:
1913 			width = ni->highx - ni->lowx;
1914 			height = ni->highy - ni->lowy;
1915 			unitsize = width / 10;
1916 			if (height < unitsize * 6) unitsize = height / 6;
1917 			*lx = 0;
1918 			*hx = unitsize/2;
1919 			*ly = *hy = 0;
1920 			break;
1921 #endif
1922 		default:
1923 			tech_nodeprotosizeoffset(ni->proto, lx, ly, hx, hy, lambdaofnode(ni));
1924 			break;
1925 	}
1926 }
1927 
sch_shapeportpoly(NODEINST * ni,PORTPROTO * pp,POLYGON * poly,XARRAY trans,BOOLEAN purpose)1928 void sch_shapeportpoly(NODEINST *ni, PORTPROTO *pp, POLYGON *poly, XARRAY trans,
1929 	BOOLEAN purpose)
1930 {
1931 	REGISTER INTBIG pindex, i, e, total, besti, xposition, yposition, x, y, lambda,
1932 		wantx, wanty, bestdist, bestx, besty, dist, width, height;
1933 	REGISTER PORTARCINST *pi;
1934 	REGISTER ARCINST *ai;
1935 	REGISTER WINDOWPART *w;
1936 
1937 	pindex = ni->proto->primindex;
1938 
1939 	switch (ni->proto->primindex)
1940 	{
1941 #ifdef SCALABLEGATES
1942 		case NAND:
1943 			width = ni->highx - ni->lowx;
1944 			height = ni->highy - ni->lowy;
1945 			lambda = width / 8;
1946 			if (height < lambda * 6) lambda = height / 6;
1947 			break;
1948 		case NOR:
1949 		case NXOR:
1950 			width = ni->highx - ni->lowx;
1951 			height = ni->highy - ni->lowy;
1952 			lambda = width / 10;
1953 			if (height < lambda * 6) lambda = height / 6;
1954 			break;
1955 #endif
1956 		default:
1957 			lambda = lambdaofnode(ni);
1958 			break;
1959 	}
1960 
1961 	/* special case for extendible primitives */
1962 	if (purpose && sch_nodeprotos[pindex-1]->portlist[0].addr == pp)
1963 	{
1964 		/* initialize */
1965 		wantx = poly->xv[0];   wanty = poly->yv[0];
1966 		poly->count = 1;
1967 		poly->style = FILLED;
1968 		bestdist = MAXINTBIG;
1969 		besti = bestx = besty = 0;
1970 
1971 		/* schematic gates must keep connections discrete and separate */
1972 		if (pindex == NAND || pindex == NOR || pindex == NXOR || pindex == NMUX)
1973 		{
1974 			/* determine total number of arcs already on this port */
1975 			for(total=0, pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1976 				if (pi->proto == pp) total++;
1977 
1978 			/* cycle through the arc positions */
1979 			total = maxi(total+2, 3);
1980 			for(i=0; i<total; i++)
1981 			{
1982 				/* compute the position along the left edge */
1983 				yposition = (i+1)/2 * WHOLE * 2;
1984 				if ((i&1) != 0) yposition = -yposition;
1985 
1986 				/* compute indentation (for OR and XOR) */
1987 				if (pindex != NMUX) xposition = -K4; else
1988 					xposition = -(ni->highx - ni->lowx) * 4 / 10 * WHOLE / lambda;
1989 				if (pindex == NOR || pindex == NXOR) switch (i)
1990 				{
1991 					case 0: xposition += T0;   break;
1992 					case 1:
1993 					case 2: xposition += H0;   break;
1994 				}
1995 
1996 				/* fill the polygon with that point */
1997 				x = getrange(ni->lowx, ni->highx, 0, xposition, lambda);
1998 				y = getrange(ni->lowy, ni->highy, 0, yposition, lambda);
1999 				xform(x, y, &poly->xv[0], &poly->yv[0], trans);
2000 				x = poly->xv[0];   y = poly->yv[0];
2001 
2002 				/* check for duplication */
2003 				for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2004 				{
2005 					ai = pi->conarcinst;
2006 					if (ai->end[0].portarcinst == pi) e = 0; else e = 1;
2007 					if (ai->end[e].xpos == x && ai->end[e].ypos == y) break;
2008 				}
2009 
2010 				/* if there is no duplication, this is a possible position */
2011 				if (pi == NOPORTARCINST)
2012 				{
2013 					dist = abs(wantx - x) + abs(wanty - y);
2014 					if (dist < bestdist)
2015 					{
2016 						bestdist = dist;   bestx = x;   besty = y;   besti = i;
2017 					}
2018 				}
2019 			}
2020 			if (bestdist == MAXINTBIG) ttyputerr(_("Warning: cannot find gate port"));
2021 
2022 			/* set the closest port */
2023 			poly->xv[0] = bestx;   poly->yv[0] = besty;
2024 
2025 			/* make sure the node is large enough */
2026 			if (besti*lambda*2 >= ni->highy - ni->lowy)
2027 			{
2028 				startobjectchange((INTBIG)ni, VNODEINST);
2029 				modifynodeinst(ni, 0, -lambda*2, 0, lambda*2, 0, 0);
2030 				endobjectchange((INTBIG)ni, VNODEINST);
2031 
2032 				/* make this gate change visible if it is in a window */
2033 				for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2034 					if (w->curnodeproto == ni->parent) break;
2035 				if (w != NOWINDOWPART) (void)asktool(us_tool, x_("flush-changes"));
2036 			}
2037 			return;
2038 		}
2039 
2040 		/* switches must discretize the location of connections */
2041 		if (pindex == NSWITCH)
2042 		{
2043 			/* cycle through the possible positions */
2044 			total = (ni->highy - ni->lowy) / lambda / 2;
2045 			for(i=0; i<total; i++)
2046 			{
2047 				yposition = i * 2 * WHOLE + K1;
2048 				xposition = -K2;
2049 				x = getrange(ni->lowx, ni->highx, 0, xposition, lambda);
2050 				y = getrange(ni->lowy, ni->highy, -H0, yposition, lambda);
2051 				xform(x, y, &poly->xv[0], &poly->yv[0], trans);
2052 				x = poly->xv[0];   y = poly->yv[0];
2053 				dist = abs(wantx - x) + abs(wanty - y);
2054 				if (dist < bestdist)
2055 				{
2056 					bestdist = dist;   bestx = x;   besty = y;   besti = i;
2057 				}
2058 			}
2059 			if (bestdist == MAXINTBIG) ttyputerr(_("Warning: cannot find switch port"));
2060 
2061 			/* set the closest port */
2062 			poly->xv[0] = bestx;   poly->yv[0] = besty;
2063 			return;
2064 		}
2065 	}
2066 	tech_fillportpoly(ni, pp, poly, trans, sch_nodeprotos[pindex-1], CLOSED, lambda);
2067 }
2068 
sch_arcpolys(ARCINST * ai,WINDOWPART * win)2069 INTBIG sch_arcpolys(ARCINST *ai, WINDOWPART *win)
2070 {
2071 	return(sch_intarcpolys(ai, win, &tech_oneprocpolyloop, &sch_oneprocpolyloop));
2072 }
2073 
sch_intarcpolys(ARCINST * ai,WINDOWPART * win,POLYLOOP * pl,SCHPOLYLOOP * schpl)2074 INTBIG sch_intarcpolys(ARCINST *ai, WINDOWPART *win, POLYLOOP *pl, SCHPOLYLOOP *schpl)
2075 {
2076 	REGISTER INTBIG i;
2077 
2078 	i = sch_arcprotos[ai->proto->arcindex]->laycount;
2079 	schpl->bubblebox = schpl->arrowbox = -1;
2080 	if ((ai->userbits&(ISNEGATED|NOTEND0)) == ISNEGATED) schpl->bubblebox = i++;
2081 	if ((ai->userbits&ISDIRECTIONAL) != 0) schpl->arrowbox = i++;
2082 
2083 	/* add in displayable variables */
2084 	pl->realpolys = i;
2085 	i += tech_displayableavars(ai, win, pl);
2086 	return(i);
2087 }
2088 
sch_shapearcpoly(ARCINST * ai,INTBIG box,POLYGON * poly)2089 void sch_shapearcpoly(ARCINST *ai, INTBIG box, POLYGON *poly)
2090 {
2091 	sch_intshapearcpoly(ai, box, poly, &tech_oneprocpolyloop, &sch_oneprocpolyloop);
2092 }
2093 
sch_intshapearcpoly(ARCINST * ai,INTBIG box,POLYGON * poly,POLYLOOP * pl,SCHPOLYLOOP * schpl)2094 void sch_intshapearcpoly(ARCINST *ai, INTBIG box, POLYGON *poly, POLYLOOP *pl, SCHPOLYLOOP *schpl)
2095 {
2096 	REGISTER INTBIG aindex, bubbleend;
2097 	REGISTER INTBIG angle;
2098 	REGISTER INTBIG x1,y1, cosdist, sindist, x2,y2, lambda, i,
2099 		saveendx, saveendy, bubblesize;
2100 	REGISTER TECH_ARCLAY *thista;
2101 
2102 	/* handle displayable variables */
2103 	if (box >= pl->realpolys)
2104 	{
2105 		(void)tech_filldisplayableavar(ai, poly, pl->curwindowpart, 0, pl);
2106 		return;
2107 	}
2108 
2109 	/* initialize for the arc */
2110 	aindex = ai->proto->arcindex;
2111 	thista = &sch_arcprotos[aindex]->list[box];
2112 	poly->layer = thista->lay;
2113 	poly->desc = sch_layers[poly->layer];
2114 	lambda = lambdaofarc(ai);
2115 	if (schpl->bubblebox < 0 && schpl->arrowbox < 0)
2116 	{
2117 		/* simple arc */
2118 		makearcpoly(ai->length, ai->width-thista->off*lambda/WHOLE,
2119 			ai, poly, thista->style);
2120 		return;
2121 	}
2122 
2123 	/* prepare special information for negated and/or directional arcs */
2124 	bubbleend = 0;
2125 	x1 = ai->end[0].xpos;   y1 = ai->end[0].ypos;
2126 	x2 = ai->end[1].xpos;   y2 = ai->end[1].ypos;
2127 	angle = ((ai->userbits&AANGLE) >> AANGLESH) * 10;
2128 	if ((ai->userbits&REVERSEEND) != 0)
2129 	{
2130 		i = x1;   x1 = x2;   x2 = i;
2131 		i = y1;   y1 = y2;   y2 = i;
2132 		bubbleend = 1;
2133 		angle = (angle+1800) % 3600;
2134 	}
2135 	bubblesize = sch_bubblediameter * lambda;
2136 	cosdist = mult(cosine(angle), bubblesize) / WHOLE;
2137 	sindist = mult(sine(angle), bubblesize) / WHOLE;
2138 
2139 	/* handle the main body of the arc */
2140 	if (box == 0)
2141 	{
2142 		if (schpl->bubblebox >= 0)
2143 		{
2144 			/* draw the arc, shortened at the end for the negating bubble */
2145 			saveendx = ai->end[bubbleend].xpos;
2146 			saveendy = ai->end[bubbleend].ypos;
2147 			ai->end[bubbleend].xpos = x1 + cosdist;
2148 			ai->end[bubbleend].ypos = y1 + sindist;
2149 			makearcpoly(ai->length-sch_bubblediameter,
2150 				ai->width-thista->off*lambda/WHOLE, ai, poly, thista->style);
2151 			ai->end[bubbleend].xpos = saveendx;
2152 			ai->end[bubbleend].ypos = saveendy;
2153 		} else
2154 		{
2155 			makearcpoly(ai->length, ai->width-thista->off*lambda/WHOLE,
2156 				ai, poly, thista->style);
2157 		}
2158 		return;
2159 	}
2160 
2161 	/* draw the negating bubble */
2162 	if (box == schpl->bubblebox)
2163 	{
2164 		poly->count = 2;
2165 		if (poly->limit < 2) (void)extendpolygon(poly, 2);
2166 		poly->xv[0] = x1 + cosdist / 2;
2167 		poly->yv[0] = y1 + sindist / 2;
2168 		poly->xv[1] = x1;   poly->yv[1] = y1;
2169 		poly->style = CIRCLE;
2170 		return;
2171 	}
2172 
2173 	/* draw the directional arrow */
2174 	if (box == schpl->arrowbox)
2175 	{
2176 		if ((ai->userbits&(ISNEGATED|NOTEND0)) == ISNEGATED)
2177 		{
2178 			x1 += cosdist;
2179 			y1 += sindist;
2180 		}
2181 		poly->style = VECTORS;
2182 		poly->layer = -1;
2183 		if (aindex == ABUS)
2184 		{
2185 			poly->desc = &sch_t_lay;
2186 			x2 -= cosdist / 2;
2187 			y2 -= sindist / 2;
2188 		}
2189 		if (poly->limit < 2) (void)extendpolygon(poly, 2);
2190 		poly->count = 2;
2191 		poly->xv[0] = x1;   poly->yv[0] = y1;
2192 		poly->xv[1] = x2;   poly->yv[1] = y2;
2193 		if ((ai->userbits&NOTEND1) == 0)
2194 			tech_addheadarrow(poly, angle, x2, y2, lambda);
2195 	}
2196 }
2197 
sch_allarcpolys(ARCINST * ai,POLYLIST * plist,WINDOWPART * win)2198 INTBIG sch_allarcpolys(ARCINST *ai, POLYLIST *plist, WINDOWPART *win)
2199 {
2200 	REGISTER INTBIG tot, j;
2201 	POLYLOOP mypl;
2202 	SCHPOLYLOOP myschpl;
2203 
2204 	mypl.curwindowpart = win;
2205 	tot = sch_intarcpolys(ai, win, &mypl, &myschpl);
2206 	tot = mypl.realpolys;
2207 	if (ensurepolylist(plist, tot, db_cluster)) return(-1);
2208 	for(j = 0; j < tot; j++)
2209 	{
2210 		sch_intshapearcpoly(ai, j, plist->polygons[j], &mypl, &myschpl);
2211 	}
2212 	return(tot);
2213 }
2214