Jspice3
netlist.c
Go to the documentation of this file.
1 /***************************************************************************
2 SCED - Schematic Capture Editor
3 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
4 Copyright 1990 Regents of the University of California. All rights reserved.
5 Authors: 1981 Giles C. Billingsley (parts of KIC layout editor)
6  1992 Stephen R. Whiteley
7 ****************************************************************************/
8 
9 /* SCED routines for manipulating the property tables to
10  * establish connectivity for netlist generation.
11  */
12 
13 #include "spice.h"
14 #include "sced.h"
15 #include "scedmacs.h"
16 
17 #define umalloc(u) (union u*)tmalloc(sizeof(union u))
18 
19 /***********************************************************************
20  *
21  * Routines to reflect circuit changes in internal element properties.
22  *
23  ***********************************************************************/
24 
25 
26 void
28 
29 /* Replace master relative coordinates with coordinates relative to
30  * the current cell. Called from CDEndMakeCall().
31  */
32 struct o *Pointer;
33 {
34  struct prpty *PDesc;
35  long X,Y;
36 
37  for (PDesc = Pointer->oPrptyList; PDesc; PDesc = PDesc->prpty_Succ) {
38  switch (PDesc->prpty_Value) {
39  case P_NODE:
40  TPoint((long*)&PDesc->prpty_Data->p_node.x,
41  (long*)&PDesc->prpty_Data->p_node.y);
42  continue;
43  case P_MUT:
44  TPoint((long*)&PDesc->prpty_Data->p_mut.x1,
45  (long*)&PDesc->prpty_Data->p_mut.y1);
46  TPoint((long*)&PDesc->prpty_Data->p_mut.x2,
47  (long*)&PDesc->prpty_Data->p_mut.y2);
48  continue;
49  case P_BRANCH:
50  TPoint((long*)&PDesc->prpty_Data->p_branch.x,
51  (long*)&PDesc->prpty_Data->p_branch.y);
52  TPoint((long*)&PDesc->prpty_Data->p_branch.r1,
53  (long*)&PDesc->prpty_Data->p_branch.r2);
54  X = 0;
55  Y = 0;
56  TPoint(&X,&Y);
57  PDesc->prpty_Data->p_branch.r1 -= X;
58  PDesc->prpty_Data->p_branch.r2 -= Y;
59  continue;
60  }
61  }
62 }
63 
64 
65 static void
66 update_device(odesc, refcnts)
67 
68 /* New in p6.
69  * Set the device name index. The refcnts arg is a pointer to an array
70  * of 128 ints, and should be cleared before starting the successive
71  * calls to this routine for each device or subcircuit.
72  * The key character of the name field indexes the array.
73  */
74 struct o *odesc;
75 int refcnts[];
76 {
77  struct prpty *pdesc;
78 
79  for (pdesc = odesc->oPrptyList; pdesc; pdesc = pdesc->prpty_Succ) {
80  if (pdesc->prpty_Value == P_NAME) {
81  if (pdesc->prpty_Data->p_name.subname == NULL) {
82  /* a device */
83  pdesc->prpty_Data->p_name.num =
84  ++(refcnts[(*pdesc->prpty_Data->p_name.name & 0x7f)]);
85  }
86  else {
87  /* a subcircuit */
88  pdesc->prpty_Data->p_name.num = ++(refcnts['X']);
89  return;
90  }
91  break;
92  }
93  }
94 }
95 
96 
97 void
99 
100 /* Assign initial properties to newly created wire. Called from wires.c */
101 struct o *Pointer;
102 {
103  struct prpty *PDesc;
104 
105  PDesc = alloc(prpty);
106  PDesc->prpty_Data = umalloc(prp_data);
107  PDesc->prpty_Value = P_NODE;
108  PDesc->prpty_Succ = Pointer->oPrptyList;
109  Pointer->oPrptyList = PDesc;
110 }
111 
112 
113 
114 /***********************************************************************
115  *
116  * Routines to create a spice deck for the circuit.
117  *
118  ***********************************************************************/
119 
120 #ifdef __STDC__
121 static void spice_deck_sort(struct line*);
122 static int lcomp(char**,char**);
123 #else
124 static void spice_deck_sort();
125 static int lcomp();
126 #endif
127 
128 char *MenuSPICE = "spice";
129 
130 
131 void
133 
134 /* Generate the complete SPICE listing */
135 {
136  FILE *fp;
137  char *c;
138  struct line *d,*d0;
139 
140  sprintf(TypeOut,"%s",Parameters.kpCellName);
141  if ((c = strchr(TypeOut,'.')) != NULL)
142  *c = '\0';
143  strcat(TypeOut,".ckt");
144  fp = fopen(TypeOut,"w");
145  if (fp == NULL) {
146  ShowPrompt("Can't open netlist file.");
147  return;
148  }
150  sprintf(TypeOut + 80,"Netlist is in file %s.",TypeOut);
151  ShowPrompt(TypeOut + 80);
152  d0 = MakeSpiceDeck();
153  for (d = d0; d; d = d->li_next)
154  fprintf(fp,"%s\n",d->li_line);
155  inp_deckfree(d0);
156  fclose(fp);
158 }
159 
160 
161 void
163 
164 /* Dump the complete spice listing to a file. */
165 FILE *fp;
166 {
167  struct line *d0,*d,*d1;
168 
169  d0 = MakeSpiceDeck();
170  for (d = d0; d; d = d->li_next) {
171  if (d->li_actual != NULL) {
172  for (d1 = d->li_actual; d1; d1 = d1->li_next)
173  fprintf(fp,"%s\n",d1->li_line);
174  }
175  else
176  fprintf(fp,"%s\n",d->li_line);
177  }
178  inp_deckfree(d0);
179 }
180 
181 
182 struct line *
184 
185 /* return a linked list of line structures representing the circuit */
186 {
187  struct line *line,*d;
188  int count;
189 
191  sprintf(TypeOut,"Generated by SCED from file %s",Parameters.kpCellName);
192  line = AllocateLine(TypeOut);
194  for (d = line; d->li_next; d = d->li_next) ;
195  d->li_next = AllocateLine(".end");
196  d->li_next->li_next = NULL;
197  count = 0;
198  for (d = line; d; d = d->li_next)
199  d->li_linenum = count++;
200  return (line);
201 }
202 
203 
204 struct line *
205 SpiceList(CellDesc)
206 
207 /* Return a SPICE deck for the circuit in CellDesc, and recursively add
208  * subcircuits.
209  */
210 struct s *CellDesc;
211 {
212  struct g *GenDesc;
213  struct o *Pointer;
214  struct s *Desc, *TmpD;
215  struct m *MDesc;
216  struct prpty *PDesc;
217  struct line *d,*d1,*d0 = NULL;
218  union prp_data *p_data;
219  int nodes[20];
220  int foundsc;
221  int i,maxn;
222  char *device, *subname;
223  char *value,*model, *extra;
224  char *name, *s;
225 
226  QueueModel(NULL);
227 
228  /* need this for hypertext */
229  TmpD = Parameters.kpCellDesc;
230  Parameters.kpCellDesc = CellDesc;
231  HYinit();
232 
233  /* first add device and subcircuit calls */
234  if (Not CDInitGen(CellDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
235  CDINFINITY,&GenDesc)) MallocFailed();
236 
237  loop {
238 
239  CDGen(CellDesc,GenDesc,&Pointer);
240  if (Pointer == NULL) break;
241  if (Pointer->oInfo == SQ_GONE) continue;
242  /* skip gnd */
243  name = ((struct c *)Pointer->oRep)->cMaster->mName;
244  if (cieq(name,"gnd")) continue;
245 
246  PDesc = Pointer->oPrptyList;
247 
248  for (i = 0; i < 20; i++)
249  nodes[i] = 0;
250  maxn = 0;
251  device = NULL;
252  subname = NULL;
253  model = NULL;
254  value = NULL;
255  extra = NULL;
256 
257  for (; PDesc; PDesc = PDesc->prpty_Succ) {
258  p_data = PDesc->prpty_Data;
259  switch (PDesc->prpty_Value) {
260  case P_NODE:
261  nodes[p_data->p_node.inode] = p_data->p_node.enode;
262  if (maxn < p_data->p_node.inode)
263  maxn = p_data->p_node.inode;
264  continue;
265  case P_NAME:
266  device = tmalloc(strlen(p_data->p_name.name)+10);
267  sprintf(device,"%s%d",
268  p_data->p_name.name,p_data->p_name.num);
269  if (p_data->p_name.subname) {
270  subname = CopyString(p_data->p_name.subname);
271  }
272  continue;
273  case P_MODEL:
274  if (p_data) {
275  model = HYtostr((struct hprlist*)p_data);
276  QueueModel(model);
277  }
278  continue;
279  case P_VALUE:
280  if (p_data) {
281  value = HYtostr((struct hprlist*)p_data);
282  }
283  continue;
284  case P_INITC:
285  if (p_data) {
286  extra = HYtostr((struct hprlist*)p_data);
287  }
288  continue;
289  }
290  }
291  if (!device)
292  /* should never happen */
293  continue;
294 
295  for (s = TypeOut,i = 0; i <= maxn; i++) {
296  sprintf(s," %d",nodes[i]);
297  while (*s) s++;
298  }
299  i = strlen(device) + strlen(TypeOut) + 1;
300  if (subname)
301  i += strlen(subname) + 1;
302  if (model)
303  i += strlen(model) + 1;
304  if (value)
305  i += strlen(value) + 1;
306  if (extra)
307  i += strlen(extra) + 1;
308 
309  device = trealloc(device,i+1);
310  s = device;
311  while (*s) s++;
312  *s++ = ' ';
313  strcpy(s,TypeOut);
314  while (*s) s++;
315  if (subname) {
316  *s++ = ' ';
317  strcpy(s,subname);
318  free(subname);
319  while (*s) s++;
320  }
321  if (model) {
322  *s++ = ' ';
323  strcpy(s,model);
324  free(model);
325  while (*s) s++;
326  }
327  if (value) {
328  *s++ = ' ';
329  strcpy(s,value);
330  free(value);
331  while (*s) s++;
332  }
333  if (extra) {
334  *s++ = ' ';
335  strcpy(s,extra);
336  free(extra);
337  while (*s) s++;
338  }
339 
340  if (d0 == NULL)
341  d = d0 = AllocateLine(device);
342  else {
343  d->li_next = AllocateLine(device);
344  d = d->li_next;
345  }
346  txfree(device);
347  }
348 
349  d1 = PrintMutual(CellDesc);
350  if (d0 == NULL)
351  d = d0 = d1;
352  else {
353  d->li_next = d1;
354  }
355  for (; d->li_next; d = d->li_next) ;
356 
357  /* sort the element cards */
358  spice_deck_sort(d0);
359 
360  /* now expand the subcircuits */
361  MDesc = CellDesc->sMasterList;
362  for (; MDesc; MDesc = MDesc->mSucc) {
363  if (Not CDOpen(MDesc->mName,&Desc,'r')) continue;
365  continue;
366  for (i = 0; i < 20; i++)
367  nodes[i] = 0;
368  maxn = 0;
369  subname = NULL;
370  PDesc = Desc->sPrptyList;
371  Connect(Desc);
372  foundsc = False;
373  for (; PDesc; PDesc = PDesc->prpty_Succ) {
374  p_data = PDesc->prpty_Data;
375  switch (PDesc->prpty_Value) {
376  case P_NODE:
377  nodes[p_data->p_node.inode] = p_data->p_node.enode;
378  if (maxn < p_data->p_node.inode)
379  maxn = p_data->p_node.inode;
380  continue;
381  case P_NAME:
382  /* The third entry in the name field signifies
383  * a subcircuit. Devices from the library
384  * have only two entries.
385  */
386  if (p_data->p_name.subname == NULL)
387  goto next;
388  subname = CopyString(p_data->p_name.subname);
389  foundsc = True;
390  continue;
391  case P_MODEL:
392  case P_VALUE:
393  case P_INITC:
394  continue;
395  }
396  }
397  if (foundsc) {
398  sprintf(TypeOut,".subckt %s",subname);
399  s = TypeOut;
400  while (*s) s++;
401  for (i = 0; i <= maxn; i++) {
402  sprintf(s," %d",nodes[i]);
403  while (*s) s++;
404  }
405  if (d0 == NULL)
406  d = d0 = AllocateLine(TypeOut);
407  else {
409  d = d->li_next;
410  }
411  d->li_next = SpiceList(Desc);
412  sprintf(TypeOut,".ends %s",subname);
413  free(subname);
414  for (; d->li_next; d = d->li_next) ;
416  d = d->li_next;
417  }
418 next:
419  ;
420  }
421  d1 = PrintModels();
422 
423  if (d0 == NULL)
424  d0 = d1;
425  else
426  d->li_next = d1;
427 
428  Parameters.kpCellDesc = TmpD;
429  return (d0);
430 }
431 
432 
433 static void
435 
436 struct line *line;
437 {
438  struct line *l;
439  char **stuff;
440  int i;
441 
442  for (i = 0,l = line; l; i++,l = l->li_next) ;
443  if (i < 2) return;
444  stuff = (char **)malloc(i*sizeof(char *));
445  if (stuff == NULL) MallocFailed();
446  for (i = 0, l = line; l; i++,l = l->li_next)
447  stuff[i] = l->li_line;
448  qsort((char *) stuff, i, sizeof (char *),
449 #if __STDC__
450  (int(*)(const void*,const void*))lcomp);
451 #else
452  lcomp);
453 #endif
454  for (i = 0, l = line; l; i++,l = l->li_next)
455  l->li_line = stuff[i];
456  free(stuff);
457  return;
458 }
459 
460 
461 static int
463 
464 char **s, **t;
465 {
466  return (strcmp(*s,*t));
467 }
468 
469 
470 /***********************************************************************
471  *
472  * Routines to establish circuit connectivity.
473  *
474  ***********************************************************************/
475 
476 /* element list */
477 struct ww {
478  struct o *ww_ptr;
479  struct ww *ww_next;
480 };
481 
482 #ifdef __STDC__
483 static int is_wire_grounded(struct o*,struct p*);
484 static void set_wire_node(struct o*,int);
485 static void connect_wires(struct ww*,struct o*,struct o*);
486 static void change_wire_node(struct ww*,int,int);
487 static void renumber_wires(struct ww*,int*);
488 static void connect_wire_to_device(struct o*,struct o*);
489 static void connect_ground_to_device(struct o*,struct p*);
490 static void connect_devices(struct o*,struct o*,int*);
491 static void set_device_node(struct o*,int*);
492 static int find_node(struct ww*,struct ww*,long,long);
493 static void ww_free(struct ww*);
494 static void p_free(struct p*);
495 #else
496 static int is_wire_grounded();
497 static void set_wire_node();
498 static void connect_wires();
499 static void change_wire_node();
500 static void renumber_wires();
501 static void connect_wire_to_device();
502 static void connect_ground_to_device();
503 static void connect_devices();
504 static void set_device_node();
505 static int find_node();
506 static void ww_free();
507 static void p_free();
508 #endif
509 
510 
511 void
513 
514 struct s *CellDesc;
515 {
516  struct s *Desc, *TmpD;
517  struct m *MDesc;
518 
519  Connect(CellDesc);
520 
521  /* need this for hypertext */
522  TmpD = Parameters.kpCellDesc;
523  Parameters.kpCellDesc = CellDesc;
524  HYinit();
525 
526  /* now expand the subcircuits */
527  MDesc = CellDesc->sMasterList;
528  for (; MDesc; MDesc = MDesc->mSucc) {
529  if (Not CDOpen(MDesc->mName,&Desc,'r')) continue;
531  continue;
532  ConnectRecursive(Desc);
533  }
534  Parameters.kpCellDesc = TmpD;
535 }
536 
537 
538 void
539 Connect(CellDesc)
540 
541 /* Assign node numbers to the terminals and wires in CellDesc */
542 struct s *CellDesc;
543 {
544  struct g *GenDesc;
545  struct o *Pointer;
546  struct prpty *PDesc;
547  struct ww *w0 = NULL, *d0 = NULL;
548  struct p *g0 = NULL, *g;
549  struct ww *w, *wx;
550  struct m *MDesc;
551  char *name;
552  int i, count;
553  int refcnts[128];
554 
555  /* Make a list of wires, and set the node to 0. */
556 
557  if (Not CDInitGen(CellDesc,1,-CDINFINITY,-CDINFINITY,
558  CDINFINITY,CDINFINITY,&GenDesc)) MallocFailed();
559 
560  loop {
561  CDGen(CellDesc,GenDesc,&Pointer);
562  if (Pointer == NULL) break;
563  if (Pointer->oInfo == SQ_GONE Or Pointer->oInfo == SQ_INCMPLT)
564  continue;
565  if (Pointer->oType == CDWIRE) {
566  if (w0 == NULL)
567  w = w0 = alloc(ww);
568  else {
569  w->ww_next = alloc(ww);
570  w = w->ww_next;
571  }
572  w->ww_ptr = Pointer;
573  PDesc = Pointer->oPrptyList;
574  for (; PDesc; PDesc = PDesc->prpty_Succ) {
575  if (PDesc->prpty_Value != P_NODE) continue;
576  PDesc->prpty_Data->p_node.enode = 0;
577  break;
578  }
579  }
580  }
581  if (w0 != NULL)
582  w->ww_next = NULL;
583 
584  /* Set the reference counts to zero. Entries are used as counters
585  * for naming devices.
586  */
587  for (i = 0; i < 128; i++)
588  refcnts[i] = 0;
589 
590  /* Make a list of devices, and a list of ground coordinates.
591  * Set the device terminal nodes to -1.
592  */
593 
594  if (Not CDInitGen(CellDesc,0,-CDINFINITY,-CDINFINITY,CDINFINITY,
595  CDINFINITY,&GenDesc)) MallocFailed();
596 
597  loop {
598  CDGen(CellDesc,GenDesc,&Pointer);
599  if (Pointer == NULL) break;
600  if (Pointer->oInfo == SQ_GONE) continue;
601 
602  name = ((struct c *)Pointer->oRep)->cMaster->mName;
603  if (cieq(name,"gnd")) {
604  /* ground device */
605  if (g0 == NULL)
606  g = g0 = alloc(p);
607  else {
608  g->pSucc = alloc(p);
609  g = g->pSucc;
610  }
611  PDesc = Pointer->oPrptyList;
612  for (; PDesc; PDesc = PDesc->prpty_Succ) {
613  if (PDesc->prpty_Value != P_NODE) continue;
614  g->pX = PDesc->prpty_Data->p_node.x;
615  g->pY = PDesc->prpty_Data->p_node.y;
616  break;
617  }
618  }
619  else {
620  if (d0 == NULL)
621  w = d0 = alloc(ww);
622  else {
623  w->ww_next = alloc(ww);
624  w = w->ww_next;
625  }
626  w->ww_ptr = Pointer;
627  PDesc = Pointer->oPrptyList;
628  for (; PDesc; PDesc = PDesc->prpty_Succ) {
629  if (PDesc->prpty_Value != P_NODE) continue;
630  PDesc->prpty_Data->p_node.enode = -1;
631  }
632  }
633  update_device(Pointer, refcnts);
634  }
635  if (d0 != NULL)
636  w->ww_next = NULL;
637  if (g0 != NULL)
638  g->pSucc = NULL;
639 
640  for (count = 0,w = w0; w; w = w->ww_next)
641  if (!is_wire_grounded(w->ww_ptr,g0)) {
642  count++;
643  set_wire_node(w->ww_ptr,count);
644  }
645 
646  for (w = w0; w; w = w->ww_next)
647  for (wx = w->ww_next; wx; wx = wx->ww_next)
648  connect_wires(w0,w->ww_ptr,wx->ww_ptr);
649 
650  renumber_wires(w0,&count);
651 
652  for (w = w0; w; w = w->ww_next)
653  for (wx = d0; wx; wx = wx->ww_next)
655 
656  for (w = d0; w; w = w->ww_next)
658 
659  for (w = d0; w; w = w->ww_next)
660  for (wx = w->ww_next; wx; wx = wx->ww_next)
661  connect_devices(w->ww_ptr,wx->ww_ptr,&count);
662 
663  for (w = d0; w; w = w->ww_next)
664  set_device_node(w->ww_ptr,&count);
665 
666  /* now set the subckt connections */
667  PDesc = CellDesc->sPrptyList;
668  for (; PDesc; PDesc = PDesc->prpty_Succ) {
669  if (PDesc->prpty_Value != P_NODE) continue;
670  PDesc->prpty_Data->p_node.enode = find_node(w0,d0,
671  PDesc->prpty_Data->p_node.x,PDesc->prpty_Data->p_node.y);
672  }
673 
674  ww_free(w0);
675  ww_free(d0);
676  p_free(g0);
677 }
678 
679 
680 static int
682 
683 /* Return True if any vertex of the wire in Pointer matches one of the
684  * coordinates in Path.
685  */
686 struct o *Pointer;
687 struct p *Path;
688 {
689  struct p *Wpath, *w;
690 
691  Wpath = ((struct w *)Pointer->oRep)->wPath;
692 
693  for (; Wpath; Wpath = Wpath->pSucc)
694  for (w = Path; w; w = w->pSucc)
695  if (w->pX == Wpath->pX && w->pY == Wpath->pY)
696  return (True);
697 
698  return (False);
699 }
700 
701 
702 static void
704 
705 /* Set the node property value of the wire in Pointer to indx. */
706 struct o *Pointer;
707 int indx;
708 {
709  struct prpty *PDesc;
710 
711  PDesc = Pointer->oPrptyList;
712  for (; PDesc; PDesc = PDesc->prpty_Succ)
713  if (PDesc->prpty_Value == P_NODE) break;
714  if (PDesc == NULL) return;
715  PDesc->prpty_Data->p_node.enode = indx;
716 }
717 
718 
719 static void
720 connect_wires(WList,Pointer1,Pointer2)
721 
722 /* If the wires in Pointer1 and Pointer 2 have a vertex in common,
723  * equate the node parameters of the two wires, setting the higher node
724  * number to the lower.
725  */
726 struct ww *WList;
727 struct o *Pointer1,*Pointer2;
728 {
729  struct p *p1,*p2,*pp;
730  struct prpty *PDesc1,*PDesc2;
731  int node1,node2;
732 
733  p1 = ((struct w *)Pointer1->oRep)->wPath;
734  p2 = ((struct w *)Pointer2->oRep)->wPath;
735 
736  for (; p1; p1 = p1->pSucc) {
737  for (pp = p2; pp; pp = pp->pSucc) {
738 
739  if (p1->pX == pp->pX && p1->pY == pp->pY) {
740 
741  PDesc1 = Pointer1->oPrptyList;
742  PDesc2 = Pointer2->oPrptyList;
743 
744  node1 = node2 = -1;
745 
746  for (; PDesc1; PDesc1 = PDesc1->prpty_Succ) {
747  if (PDesc1->prpty_Value != P_NODE) continue;
748  node1 = PDesc1->prpty_Data->p_node.enode;
749  break;
750  }
751  for (; PDesc2; PDesc2 = PDesc2->prpty_Succ) {
752  if (PDesc2->prpty_Value != P_NODE) continue;
753  node2 = PDesc2->prpty_Data->p_node.enode;
754  break;
755  }
756  if (node1 < 0 || node2 < 0)
757  /* Things are foobar */
758  return;
759 
760  if (node1 == node2) return;
761 
762  if (node1 < node2)
763  change_wire_node(WList,node2,node1);
764  else
765  change_wire_node(WList,node1,node2);
766  return;
767  }
768  }
769  }
770 }
771 
772 
773 static void
774 change_wire_node(WList,oldnode,newnode)
775 
776 /* change wires with node oldnode to newnode */
777 struct ww *WList;
778 int oldnode,newnode;
779 {
780  struct prpty *PDesc;
781 
782  for (; WList; WList = WList->ww_next) {
783  PDesc = WList->ww_ptr->oPrptyList;
784  for (; PDesc; PDesc = PDesc->prpty_Succ) {
785  if (PDesc->prpty_Value != P_NODE) continue;
786  if (PDesc->prpty_Data->p_node.enode == oldnode)
787  PDesc->prpty_Data->p_node.enode = newnode;
788  break;
789  }
790  }
791 }
792 
793 
794 static void
796 
797 /* find a compact numbering for wire nodes */
798 struct ww *Wlist;
799 int *count;
800 {
801  struct ww *w;
802  struct prpty *PDesc;
803  int *itmp,i,sum;
804 
805  itmp = (int *) malloc((*count+1)*sizeof(int));
806  if (itmp == NULL) MallocFailed();
807 
808  for (i = 0; i <= *count; i++)
809  *(itmp+i) = 0;
810 
811  for (w = Wlist; w; w = w->ww_next) {
812  PDesc = w->ww_ptr->oPrptyList;
813  for (; PDesc; PDesc = PDesc->prpty_Succ) {
814  if (PDesc->prpty_Value != P_NODE) continue;
815  if (PDesc->prpty_Data->p_node.enode == 0) continue;
816  itmp[PDesc->prpty_Data->p_node.enode] = 1;
817  }
818  }
819 
820  for (sum = 0,i = 1; i <= *count; i++) {
821  sum += itmp[i];
822  itmp[i] = sum;
823  }
824  *count = sum;
825 
826  for (w = Wlist; w; w = w->ww_next) {
827  PDesc = w->ww_ptr->oPrptyList;
828  for (; PDesc; PDesc = PDesc->prpty_Succ) {
829  if (PDesc->prpty_Value != P_NODE) continue;
830  if (PDesc->prpty_Data->p_node.enode == 0) continue;
831  PDesc->prpty_Data->p_node.enode =
832  itmp[PDesc->prpty_Data->p_node.enode];
833  }
834  }
835  free(itmp);
836 }
837 
838 
839 static void
840 connect_wire_to_device(Pointer1,Pointer2)
841 
842 /* If a vertex of the wire in Pointer1 matches a terminal of the device in
843  * Pointer2, set the device node to match the wire node.
844  */
845 struct o *Pointer1,*Pointer2;
846 {
847  struct p *p1, *pp;
848  struct prpty *PDesc1,*PDesc2;
849  int node1;
850 
851  p1 = ((struct w *)Pointer1->oRep)->wPath;
852  PDesc1 = Pointer1->oPrptyList;
853  node1 = -1;
854  for (; PDesc1; PDesc1 = PDesc1->prpty_Succ) {
855  if (PDesc1->prpty_Value != P_NODE) continue;
856  node1 = PDesc1->prpty_Data->p_node.enode;
857  break;
858  }
859  if (node1 < 0)
860  /* trouble */
861  return;
862 
863  PDesc2 = Pointer2->oPrptyList;
864  for (; PDesc2; PDesc2 = PDesc2->prpty_Succ) {
865  if (PDesc2->prpty_Value != P_NODE) continue;
866  for (pp = p1; pp; pp = pp->pSucc) {
867  if (pp->pX == PDesc2->prpty_Data->p_node.x &&
868  pp->pY == PDesc2->prpty_Data->p_node.y) {
869  PDesc2->prpty_Data->p_node.enode = node1;
870  }
871  }
872  }
873 }
874 
875 
876 static void
878 
879 /* If any coordinate in Path matches a device terminal coordinate from
880  * Pointer, ground the device node.
881  */
882 struct o *Pointer;
883 struct p *Path;
884 {
885  struct prpty *PDesc;
886  struct p *pp;
887 
888  for (PDesc = Pointer->oPrptyList; PDesc; PDesc = PDesc->prpty_Succ) {
889  if (PDesc->prpty_Value != P_NODE) continue;
890  for (pp = Path; pp; pp = pp->pSucc) {
891  if (pp->pX == PDesc->prpty_Data->p_node.x &&
892  pp->pY == PDesc->prpty_Data->p_node.y) {
893  PDesc->prpty_Data->p_node.enode = 0;
894  }
895  }
896  }
897 }
898 
899 
900 static void
901 connect_devices(Pointer1,Pointer2,count)
902 
903 /* If any terminals in the devices in Pointer1 and Pointer2 share a
904  * coordinate, make sure both node numbers are equal and valid. Assign
905  * a new node number if necessary.
906  */
907 struct o *Pointer1,*Pointer2;
908 int *count;
909 {
910 
911  struct prpty *PDesc1,*PDesc2,*pd;
912  int int11,int21;
913  int X,Y;
914 
915  PDesc1 = Pointer1->oPrptyList;
916  PDesc2 = Pointer2->oPrptyList;
917 
918  for (; PDesc1; PDesc1 = PDesc1->prpty_Succ) {
919  if (PDesc1->prpty_Value != P_NODE) continue;
920 
921  X = PDesc1->prpty_Data->p_node.x;
922  Y = PDesc1->prpty_Data->p_node.y;
923  int11 = PDesc1->prpty_Data->p_node.enode;
924 
925  for (pd = PDesc2; pd; pd = pd->prpty_Succ) {
926  if (pd->prpty_Value != P_NODE) continue;
927 
928  if (X == pd->prpty_Data->p_node.x &&
929  Y == pd->prpty_Data->p_node.y) {
930 
931  int21 = pd->prpty_Data->p_node.enode;
932 
933  if (int11 < 0 && int21 >= 0) {
934  PDesc1->prpty_Data->p_node.enode = int21;
935  int11 = int21;
936  }
937  else if (int21 < 0 && int11 >= 0) {
938  pd->prpty_Data->p_node.enode = int11;
939  }
940  else if (int11 < 0 && int21 < 0) {
941  (*count)++;
942  PDesc1->prpty_Data->p_node.enode = *count;
943  pd->prpty_Data->p_node.enode = *count;
944  int11 = *count;
945  }
946  else if (int11 != int21) {
947  /* trouble */
948 
949  }
950  }
951  }
952  }
953 }
954 
955 
956 static void
958 
959 /* Assign node numbers to unassigned device terminals */
960 struct o *Pointer;
961 int *count;
962 {
963  struct prpty *PDesc;
964 
965  PDesc = Pointer->oPrptyList;
966  for (; PDesc; PDesc = PDesc->prpty_Succ) {
967  if (PDesc->prpty_Value != P_NODE) continue;
968  if (PDesc->prpty_Data->p_node.enode >= 0) continue;
969  (*count)++;
970  PDesc->prpty_Data->p_node.enode = *count;
971  }
972 }
973 
974 
975 static int
976 find_node(Wlist,Dlist,X,Y)
977 
978 /* Return the node number of the terminal or vertex at the given
979  * coordinates. If not found, return -1.
980  */
981 struct ww *Wlist,*Dlist;
982 long X,Y;
983 {
984  struct ww *w;
985  struct prpty *PDesc;
986  struct p *Path;
987 
988  /* first look at device terminals */
989  for (w = Dlist; w; w = w->ww_next) {
990  PDesc = w->ww_ptr->oPrptyList;
991  for (; PDesc; PDesc = PDesc->prpty_Succ) {
992  if (PDesc->prpty_Value != P_NODE) continue;
993  if (X == PDesc->prpty_Data->p_node.x &&
994  Y == PDesc->prpty_Data->p_node.y)
995  return (PDesc->prpty_Data->p_node.enode);
996  }
997  }
998 
999  /* now check wire vertices */
1000  for (w = Wlist; w; w = w->ww_next) {
1001  Path = ((struct w *)w->ww_ptr->oRep)->wPath;
1002  for (; Path; Path = Path->pSucc) {
1003  if (X == Path->pX && Y == Path->pY) {
1004  PDesc = w->ww_ptr->oPrptyList;
1005  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1006  if (PDesc->prpty_Value != P_NODE) continue;
1007  return (PDesc->prpty_Data->p_node.enode);
1008  }
1009  }
1010  }
1011  }
1012  return (-1);
1013 }
1014 
1015 
1016 static void
1018 
1019 struct ww *w;
1020 {
1021  struct ww *wn;
1022 
1023  for (; w; w = wn) {
1024  wn = w->ww_next;
1025  tfree(w);
1026  }
1027 }
1028 
1029 
1030 static void
1032 
1033 struct p *w;
1034 {
1035  struct p *wn;
1036 
1037  for (; w; w = wn) {
1038  wn = w->pSucc;
1039  tfree(w);
1040  }
1041 }
1042 
1043 
1044 
1045 /***********************************************************************
1046  *
1047  * Routines to display and modify user specified element properties.
1048  *
1049  ***********************************************************************/
1050 
1051 extern char *MenuPRPTY;
1052 
1053 #ifdef __STDC__
1054 static int prptyKB(struct o*,struct prpty*);
1055 static void global_modify(void);
1056 static int pType(int);
1057 #else
1058 static int prptyKB();
1059 static void global_modify();
1060 static int pType();
1061 #endif
1062 
1063 
1064 void
1065 ShowProperties(LookedAhead)
1066 
1067 int *LookedAhead;
1068 {
1069  struct prpty *PDesc;
1070  struct ks *SQDesc;
1071  char Types[4], *TypeIn;
1072  int Pret;
1073  int GotOne = False;
1074  char *s;
1075 
1076  Types[0]= CDSYMBOLCALL;
1077  Types[1]= CDWIRE;
1078  Types[2] = '\0';
1079 
1082 
1083  if (AreTypesInQ(Types))
1084  GotOne = True;
1085 top:
1086  if (!GotOne) {
1087  ShowPrompt(
1088 "Select object, at \">\" hit ENTER or a (add/repl), d (delete), n (break).");
1089  switch (PointLoop(LookedAhead)) {
1090  case PL_ESC:
1091  case PL_CMD:
1092  case PL_UND:
1093  goto quit;
1094  case PL_PCW:
1095  SelectTypes(Types);
1096  if (Not AreTypesInQ(Types))
1097  goto top;
1098  }
1099  }
1100  else {
1101  ShowPrompt(
1102 "Hit * for global, at \">\" hit a (add/repl), d (delete), n (next), ENTER.");
1103 
1104  switch (FBGetchar(ERASE)) {
1105  case ESCAPE:
1106  goto quit;
1107  case '*':
1108  global_modify();
1109  goto quit;
1110  default:
1111  SQComputeBB();
1113  EraseBox(&SelectQBB);
1114  Redisplay(&SelectQBB);
1115  break;
1116  }
1117  }
1118 
1119  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
1120  if (SQDesc->ksPointer->oType != CDSYMBOLCALL &&
1121  SQDesc->ksPointer->oType != CDWIRE) continue;
1123  PDesc = SQDesc->ksPointer->oPrptyList;
1124  if (PDesc == NULL) {
1125  ShowPrompt("Object has no properties. > ");
1126  if (prptyKB(SQDesc->ksPointer,NULL) == 0) goto quit;
1127  continue;
1128  }
1129  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1130  if (SQDesc->ksPointer->oType == CDWIRE) {
1131  if (PDesc->prpty_Value == P_NODE) {
1132  sprintf(TypeOut,"Wire Node Number (internal): %d > ",
1133  PDesc->prpty_Data->p_node.enode);
1135  }
1136  if ((Pret = prptyKB(SQDesc->ksPointer,NULL)) == 0)
1137  goto quit;
1138  if (Pret == -1) goto next;
1139  continue;
1140  }
1141 
1142  switch (PDesc->prpty_Value) {
1143  case P_MODEL:
1144  sprintf(TypeOut,"Model: %s > ",
1145  s = HYtostr((struct hprlist*)PDesc->prpty_Data));
1147  txfree(s);
1148  if ((Pret = prptyKB(SQDesc->ksPointer,PDesc)) == 0)
1149  goto quit;
1150  if (Pret == -1) goto next;
1151  break;
1152  case P_VALUE:
1153  sprintf(TypeOut,"Value: %s > ",
1154  s = HYtostr((struct hprlist*)PDesc->prpty_Data));
1156  txfree(s);
1157  if ((Pret = prptyKB(SQDesc->ksPointer,PDesc)) == 0)
1158  goto quit;
1159  if (Pret == -1) goto next;
1160  break;
1161  case P_INITC:
1162  sprintf(TypeOut,"Initial Conditions: %s > ",
1163  s = HYtostr((struct hprlist*)PDesc->prpty_Data));
1165  txfree(s);
1166  if ((Pret = prptyKB(SQDesc->ksPointer,PDesc)) == 0)
1167  goto quit;
1168  if (Pret == -1) goto next;
1169  break;
1170  case P_OTHER:
1171  sprintf(TypeOut,"External Property: %s > ",
1172  s = HYtostr((struct hprlist*)PDesc->prpty_Data));
1174  txfree(s);
1175  if ((Pret = prptyKB(SQDesc->ksPointer,PDesc)) == 0)
1176  goto quit;
1177  if (Pret == -1) goto next;
1178  break;
1179  case P_NAME:
1180  sprintf(TypeOut,"Device Name (internal): %s%d > ",
1181  PDesc->prpty_Data->p_name.name,
1182  PDesc->prpty_Data->p_name.num);
1184  if ((Pret = prptyKB(SQDesc->ksPointer,NULL)) == 0)
1185  goto quit;
1186  if (Pret == -1) goto next;
1187  break;
1188  case P_NODE:
1189  sprintf(TypeOut,"Node Number (internal): %d > ",
1190  PDesc->prpty_Data->p_node.enode);
1192  if ((Pret = prptyKB(SQDesc->ksPointer,NULL)) == 0)
1193  goto quit;
1194  if (Pret == -1) goto next;
1195  break;
1196  case P_BRANCH:
1197  sprintf(TypeOut,"Branch (internal) > ");
1199  if ((Pret = prptyKB(SQDesc->ksPointer,NULL)) == 0)
1200  goto quit;
1201  if (Pret == -1) goto next;
1202  break;
1203  }
1204  }
1205 next:
1207  }
1208  if (!GotOne) {
1209  SQComputeBB();
1210  SQDesel(Types);
1211  EraseBox(&SelectQBB);
1212  Redisplay(&SelectQBB);
1213  goto top;
1214  }
1215 quit:
1217  if (!GotOne) {
1218  if (AreTypesInQ(Types)) {
1219  SQComputeBB();
1220  SQDesel(Types);
1221  EraseBox(&SelectQBB);
1222  Redisplay(&SelectQBB);
1223  }
1224  }
1225  else {
1227  SQShow();
1228  }
1229  ErasePrompt();
1231 }
1232 
1233 
1234 static int
1236 
1237 /* return values: 0 (ESCAPE entered), -1 ('n' entered), 1 (otherwise) */
1238 struct o *Pointer;
1239 struct prpty *PDesc;
1240 {
1241  struct prpty *pd;
1242  struct hprlist *ht;
1243  char InChar;
1244  int Value,pv;
1245 
1246  if ((InChar = FBGetchar(DISPLAY)) == ESCAPE)
1247  return (0);
1248 
1249  if (InChar == 'n' || InChar == 'N')
1250  return (-1);
1251 
1252  if (InChar == '\0' || InChar == '\n' || InChar == '\r')
1253  goto quit;
1254 
1255  if (Pointer->oType == CDWIRE) {
1256  ShowPromptAndWait("Can't modify wire properties.");
1257  goto quit;
1258  }
1259 
1260  if (InChar == 'a' || InChar == 'A') {
1261  loop {
1262  Value = 0;
1263  ShowPrompt(
1264  "Enter property type to add (Model m Value v Init Cnd i Other o): ");
1265  if ((InChar = FBGetchar(DISPLAY)) == ESCAPE)
1266  return (0);
1267  if (InChar == '\n' || InChar == '\r') {
1268  if (PDesc != NULL)
1269  Value = PDesc->prpty_Value;
1270  else
1271  continue;
1272  }
1273  else
1274  Value = pType(InChar);
1275  pv = Value;
1276  switch (Value) {
1277  case P_MODEL:
1278  ShowPrompt("Model name? ");
1279  break;
1280  case P_VALUE:
1281  ShowPrompt("Value? ");
1282  break;
1283  case P_INITC:
1284  ShowPrompt("Initial Conditions? ");
1285  break;
1286  case P_OTHER:
1287  strcpy(TypeOut,"Load from? (");
1288  pv = 0;
1289  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1290  if (pd->prpty_Value == P_MODEL) {
1291  strcat(TypeOut,"Model m");
1292  pv = 1;
1293  break;
1294  }
1295  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1296  if (pd->prpty_Value == P_VALUE) {
1297  if (pv) strcat(TypeOut," ");
1298  strcat(TypeOut,"Value v");
1299  pv = 1;
1300  break;
1301  }
1302  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1303  if (pd->prpty_Value == P_INITC) {
1304  if (pv) strcat(TypeOut," ");
1305  strcat(TypeOut,"Init Cnd i");
1306  pv = 1;
1307  break;
1308  }
1309  if (pv) {
1310  strcat(TypeOut,"): ");
1312  if ((InChar = FBGetchar(DISPLAY)) == ESCAPE)
1313  goto quit;
1314  pv = pType(InChar);
1315  }
1316  else
1317  pv = P_OTHER;
1318  ShowPrompt("Property String? ");
1319  Value = P_OTHER;
1320  break;
1321  }
1322  break;
1323  }
1324  if (PDesc && PDesc->prpty_Value == pv)
1325  pd = PDesc;
1326  else {
1327  if (pv == P_OTHER)
1328  pd = NULL;
1329  else
1330  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1331  if (pd->prpty_Value == pv) break;
1332  }
1333  if (pd)
1334  ht = FBHyEdit((struct hprlist*)pd->prpty_Data);
1335  else
1336  ht = FBHyEdit(NULL);
1337  if (ht == NULL)
1338  return (0);
1339 
1340  if (Value == P_OTHER) {
1341  ShowPrompt("Also store in? (Model m Value v Inid Cnd i): ");
1342  if ((InChar = FBGetchar(DISPLAY)) == ESCAPE)
1343  goto quit;
1344  pv = pType(InChar);
1345  if (pv != P_OTHER) {
1346  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1347  if (pd->prpty_Value == pv) break;
1348  if (pd) {
1349  HYfree((struct hprlist*)pd->prpty_Data);
1350  pd->prpty_Data = (union prp_data*)ht;
1351  }
1352  else {
1353  pd = alloc(prpty);
1354  pd->prpty_Value = pv;
1355  pd->prpty_Data = (union prp_data*)ht;
1356  pd->prpty_Succ = Pointer->oPrptyList;
1357  Pointer->oPrptyList = pd;
1358  }
1359  ht = HYcopy(ht);
1360  }
1361  }
1362  if (PDesc && PDesc->prpty_Value == Value) {
1363  HYfree((struct hprlist*)PDesc->prpty_Data);
1364  PDesc->prpty_Data = (union prp_data*)ht;
1365  }
1366  else {
1367  for (pd = Pointer->oPrptyList; pd; pd = pd->prpty_Succ)
1368  if (pd->prpty_Value == Value) break;
1369  if (pd && Value != P_OTHER) {
1370  HYfree((struct hprlist*)pd->prpty_Data);
1371  pd->prpty_Data = (union prp_data*)ht;
1372  }
1373  else {
1374  pd = alloc(prpty);
1375  pd->prpty_Value = Value;
1376  pd->prpty_Data = (union prp_data*)ht;
1377  pd->prpty_Succ = Pointer->oPrptyList;
1378  Pointer->oPrptyList = pd;
1379  }
1380  }
1382  }
1383  else if (InChar == 'd' || InChar == 'D') {
1384  if (PDesc == NULL) {
1385  ShowPromptAndWait("No property to delete.");
1386  goto quit;
1387  }
1388  if (PDesc->prpty_Value >= 10) {
1389  ShowPromptAndWait("Can't delete internal properties.");
1390  goto quit;
1391  }
1392  pd = Pointer->oPrptyList;
1393  if (pd == PDesc)
1394  Pointer->oPrptyList = PDesc->prpty_Succ;
1395  else {
1396  /* must be in the list */
1397  for (; pd && pd->prpty_Succ != PDesc; pd = pd->prpty_Succ) ;
1398  pd->prpty_Succ = PDesc->prpty_Succ;
1399  }
1400  HYfree((struct hprlist*)PDesc->prpty_Data);
1401  tfree(PDesc);
1403  ShowPromptAndWait("Property deleted.");
1404  }
1405 quit:
1406  return (1);
1407 }
1408 
1409 
1410 static void
1412 
1413 {
1414  struct ks *SQDesc;
1415  struct prpty *pd;
1416  int val, InChar;
1417  char *name;
1418  struct hprlist *ht;
1419 
1420  ShowPrompt(
1421 "Enter property type to globally add/repl (Model m Value v Init Cnd i): ");
1422 top:
1423  if ((InChar = FBGetchar(DISPLAY)) == ESCAPE)
1424  return;
1425  val = pType(InChar);
1426  switch (val) {
1427  case P_MODEL:
1428  ShowPrompt("Model name? ");
1429  break;
1430  case P_VALUE:
1431  ShowPrompt("Value? ");
1432  break;
1433  case P_INITC:
1434  ShowPrompt("Initial Conditions? ");
1435  break;
1436  default:
1437  ShowPrompt("Bad entry, enter m,v,i or Esc to exit: ");
1438  goto top;
1439  }
1440  ht = FBHyEdit(NULL);
1441  if (ht == NULL)
1442  return;
1443 
1444  for (SQDesc = SelectQHead; SQDesc; SQDesc = SQDesc->ksSucc) {
1445  if (SQDesc->ksPointer->oType != CDSYMBOLCALL) continue;
1446  name = ((struct c *)SQDesc->ksPointer->oRep)->cMaster->mName;
1447  if (!IsCellInLib(name)) continue;
1448 
1449  for (pd = SQDesc->ksPointer->oPrptyList; pd; pd = pd->prpty_Succ)
1450  if (pd->prpty_Value == val) break;
1451  if (pd) {
1452  HYfree((struct hprlist*)pd->prpty_Data);
1453  pd->prpty_Data = (union prp_data*)HYcopy(ht);
1454  }
1455  else {
1456  pd = alloc(prpty);
1457  pd->prpty_Value = val;
1458  pd->prpty_Data = (union prp_data*)HYcopy(ht);
1459  pd->prpty_Succ = SQDesc->ksPointer->oPrptyList;
1460  SQDesc->ksPointer->oPrptyList = pd;
1461  }
1462  }
1463  HYfree(ht);
1465 }
1466 
1467 
1468 static int
1470 
1471 char c;
1472 {
1473  switch (c) {
1474  case '1':
1475  case 'm':
1476  case 'M':
1477  return (P_MODEL);
1478  case '2':
1479  case 'v':
1480  case 'V':
1481  return (P_VALUE);
1482  case '3':
1483  case 'i':
1484  case 'I':
1485  return (P_INITC);
1486  default:
1487  return (P_OTHER);
1488  }
1489 }
1490 
1491 
1492 /***********************************************************************
1493  *
1494  * Routines to create user specified subcircut connections.
1495  *
1496  ***********************************************************************/
1497 
1498 extern char *MenuSUBCT;
1499 extern char *MenuUNDO;
1500 extern char *MenuTERMS;
1501 
1502 #ifdef __STDC__
1503 static void insert_terminal(long,long);
1504 #else
1505 static void insert_terminal();
1506 #endif
1507 
1508 
1509 void
1510 Subcircuit(LookedAhead)
1511 
1512 /* Add node and name fields to cell descriptor */
1513 int *LookedAhead;
1514 {
1515  struct prpty *PDesc;
1516  int setone,count,int1,int2;
1517  long X,Y,OldX,OldY;
1518 
1520  ShowPrompt("Point to subcircuit connection points (ESC to exit).");
1521 
1523  loop {
1524  switch (PointLoop(LookedAhead)) {
1525  case PL_CMD:
1526  if (!strcmp(Parameters.kpCommand,MenuSUBCT))
1527  *LookedAhead = False;
1528  case PL_ESC:
1529  goto quit;
1530  case PL_UND:
1532  if (setone > 0) {
1533  insert_terminal(OldX,OldY);
1535  }
1536  else
1537  goto quit;
1538  break;
1539  case PL_PCW:
1540  X = SCursor.kcX;
1541  Y = SCursor.kcY;
1542  if (!SelectNode(&X,&Y)) continue;
1543  insert_terminal(X,Y);
1545  setone = True;
1546  OldX = X;
1547  OldY = Y;
1548  }
1549  }
1550 quit:
1551 
1552  /* The first (or earliest) terminal assigned is the
1553  * reference terminal. This is last on the list.
1554  */
1555  count = 0;
1556  PDesc = Parameters.kpCellDesc->sPrptyList;
1557  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1558  if (PDesc->prpty_Value != P_NODE) continue;
1559  count++;
1560  }
1561  if (count) {
1562  PDesc = Parameters.kpCellDesc->sPrptyList;
1563  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1564  if (PDesc->prpty_Value != P_NODE) continue;
1565  count--;
1566  PDesc->prpty_Data->p_node.enode = -1;
1567  PDesc->prpty_Data->p_node.inode = count;
1568  ShowMarker(ERASE,0,PDesc->prpty_Data->p_node.x,
1569  PDesc->prpty_Data->p_node.y,100,MARK_CROSS,0);
1570  }
1571  /* subckts have 3 entries in name field */
1572  PDesc = Parameters.kpCellDesc->sPrptyList;
1573  for (; PDesc; PDesc = PDesc->prpty_Succ)
1574  if (PDesc->prpty_Value == P_NAME) break;
1575  if (!PDesc) {
1576  sprintf(TypeOut,"X 0 %s",Parameters.kpCellName);
1577  if (Not CDAddProperty(Parameters.kpCellDesc,(struct o *)NULL,
1578  P_NAME,TypeOut))
1579  MallocFailed();
1580  }
1581  }
1582 
1585  ErasePrompt();
1586 }
1587 
1588 
1589 static void
1591 
1592 /* If terminal already assigned, delete assignment.
1593  * Otherwise, add new terminal.
1594  */
1595 long X,Y;
1596 {
1597  struct prpty *PDesc;
1598  struct prpty *PPrev = NULL;
1599 
1600  PDesc = Parameters.kpCellDesc->sPrptyList;
1601  for (; PDesc; PPrev = PDesc,PDesc = PDesc->prpty_Succ) {
1602  if (PDesc->prpty_Value != P_NODE) continue;
1603  if (X == PDesc->prpty_Data->p_node.x &&
1604  Y == PDesc->prpty_Data->p_node.y) {
1605  if (PPrev)
1606  PPrev->prpty_Succ = PDesc->prpty_Succ;
1607  else
1609  ShowMarker(ERASE,0,X,Y,100,MARK_CROSS,0);
1610  free(PDesc->prpty_Data);
1611  free(PDesc);
1612  return;
1613  }
1614  }
1615  sprintf(TypeOut,"-1 0 %ld %ld",X,Y);
1616  if (Not CDAddProperty(Parameters.kpCellDesc,(struct o *)NULL,
1617  P_NODE,TypeOut))
1618  MallocFailed();
1620 }
1621 
1622 
1623 int
1625 
1626 /* Do the coordinates match a circuit node? It yes, return the exact node
1627  * coordinates.
1628  */
1629 long *Xo,*Yo;
1630 {
1631  struct ka AOI;
1632  struct g *GenDesc;
1633  struct o *Pointer;
1634  struct p *Path;
1635  struct prpty *PDesc;
1636  int Layer,Delta;
1637  long X,Y,Width,*xy;
1638 
1639 
1640  if (SCursor.kcInFine == True)
1641  Delta = 5.0/View->kvFineRatio;
1642  else
1643  Delta = 5.0/View->kvCoarseRatio;
1644 
1645  AOI.kaLeft = *Xo - Delta;
1646  AOI.kaRight = *Xo + Delta;
1647  AOI.kaBottom = *Yo - Delta;
1648  AOI.kaTop = *Yo + Delta;
1649 
1650  /* first check subcircuit terminals */
1651  PDesc = Parameters.kpCellDesc->sPrptyList;
1652  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1653  if (PDesc->prpty_Value != P_NODE) continue;
1654  X = PDesc->prpty_Data->p_node.x;
1655  Y = PDesc->prpty_Data->p_node.y;
1656 
1657  if (InBox(X,Y,&AOI)) {
1658  *Xo = X;
1659  *Yo = Y;
1660  return (True);
1661  }
1662  }
1663 
1664  /* next check the devices */
1666  AOI.kaRight,AOI.kaTop,&GenDesc)) MallocFailed();
1667  loop {
1668  CDGen(Parameters.kpCellDesc,GenDesc,&Pointer);
1669  if (Pointer == NULL) break;
1670  if (Pointer->oInfo == SQ_GONE) continue;
1671 
1672  PDesc = Pointer->oPrptyList;
1673  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1674  if (PDesc->prpty_Value != P_NODE) continue;
1675  X = PDesc->prpty_Data->p_node.x;
1676  Y = PDesc->prpty_Data->p_node.y;
1677 
1678  if (InBox(X,Y,&AOI)) {
1679  tfree(GenDesc);
1680  *Xo = X;
1681  *Yo = Y;
1682  return (True);
1683  }
1684  }
1685  }
1686 
1687  /* now check wires */
1689  AOI.kaRight,AOI.kaTop,&GenDesc)) MallocFailed();
1690  loop {
1691  CDGen(Parameters.kpCellDesc,GenDesc,&Pointer);
1692  if (Pointer == NULL) break;
1693  if (Pointer->oInfo == SQ_GONE) continue;
1694  if (Pointer->oType != CDWIRE) continue;
1695  CDWire(Pointer,&Layer,&Width,&Path);
1696 
1697  for (; Path; Path = Path->pSucc)
1698  if (InBox(Path->pX,Path->pY,&AOI)) {
1699  tfree(GenDesc);
1700  *Xo = Path->pX;
1701  *Yo = Path->pY;
1702  return (True);
1703  }
1704  }
1705  return (False);
1706 }
1707 
1708 
1709 void
1711 
1712 /* Display the terminal locations of the current cell */
1713 {
1714 
1719  }
1720  else {
1724  }
1725 }
1726 
1727 
1728 void
1729 DisplayTerminals(DisplayOrErase)
1730 
1731 int DisplayOrErase;
1732 {
1733  struct prpty *PDesc;
1734 
1735  PDesc = Parameters.kpCellDesc->sPrptyList;
1736  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1737  if (PDesc->prpty_Value != P_NODE) continue;
1738  ShowMarker(DisplayOrErase,HighlightingColor,
1739  PDesc->prpty_Data->p_node.x,PDesc->prpty_Data->p_node.y,
1740  100,MARK_CROSS,0);
1741  }
1742 }
1743 
1744 
1745 
1746 /***********************************************************************
1747  *
1748  * Routines to update subcircuit connection coordinates if the
1749  * underlying element is moved.
1750  *
1751  ***********************************************************************/
1752 
1753 #ifdef __STDC__
1754 static int device_node(long,long);
1755 #else
1756 static int device_node();
1757 #endif
1758 
1759 void
1761 
1762 /* look through the cell reference points. If any correspond to an
1763  * element that was just moved, transform the reference. Save the old
1764  * union in the Info field.
1765  */
1766 struct o *Pointer;
1767 {
1768  struct ka BB;
1769  struct prpty *PDesc;
1770  struct p *Path;
1771  int Layer;
1772  long X,Y,Width,X1,Y1,X2,Y2;
1773  long *InPath();
1774 
1775  CDBB(Parameters.kpCellDesc,Pointer,
1776  &BB.kaLeft,&BB.kaBottom,&BB.kaRight,&BB.kaTop);
1777 
1778  PDesc = Parameters.kpCellDesc->sPrptyList;
1779  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1780  switch (PDesc->prpty_Value) {
1781  case P_NODE:
1782  X = PDesc->prpty_Data->p_node.x;
1783  Y = PDesc->prpty_Data->p_node.y;
1784  if (!InBox(X,Y,&BB)) continue;
1785  switch (Pointer->oType) {
1786  case CDWIRE:
1787  CDWire(Pointer,&Layer,&Width,&Path);
1788  if (InPath(20,Path,X,Y) == NULL) continue;
1789  if (device_node(X,Y)) continue;
1790  case CDSYMBOLCALL:
1791  TPoint(&X,&Y);
1792  PDesc->prpty_Info = (char*)PDesc->prpty_Data;
1793  PDesc->prpty_Data = umalloc(prp_data);
1794  PDesc->prpty_Data->p_node.x = X;
1795  PDesc->prpty_Data->p_node.y = Y;
1796  PDesc->prpty_Data->p_node.enode =
1797  ((union prp_data*)PDesc->prpty_Info)->p_node.enode;
1798  PDesc->prpty_Data->p_node.inode =
1799  ((union prp_data*)PDesc->prpty_Info)->p_node.inode;
1800  }
1801  continue;
1802  case P_MUT:
1803  /* get the transformed lower left corner */
1804  if (Pointer->oType != CDSYMBOLCALL) continue;
1805  X = PDesc->prpty_Data->p_mut.x1;
1806  Y = PDesc->prpty_Data->p_mut.y1;
1807  X1 = PDesc->prpty_Data->p_mut.x2;
1808  Y1 = PDesc->prpty_Data->p_mut.y2;
1809  if (X == BB.kaLeft && Y == BB.kaBottom) {
1810  X2 = BB.kaRight;
1811  Y2 = BB.kaTop;
1812  TPoint(&X,&Y);
1813  TPoint(&X2,&Y2);
1814  if (X > X2) X = X2;
1815  if (Y > Y2) Y = Y2;
1816  }
1817  else if (X1 == BB.kaLeft && Y1 == BB.kaBottom) {
1818  X2 = BB.kaRight;
1819  Y2 = BB.kaTop;
1820  TPoint(&X1,&Y1);
1821  TPoint(&X2,&Y2);
1822  if (X1 > X2) X1 = X2;
1823  if (Y1 > Y2) Y1 = Y2;
1824  }
1825  else
1826  continue;
1827  PDesc->prpty_Info = (char*)PDesc->prpty_Data;
1828  PDesc->prpty_Data = umalloc(prp_data);
1829  PDesc->prpty_Data->p_mut.x1 = X;
1830  PDesc->prpty_Data->p_mut.y1 = Y;
1831  PDesc->prpty_Data->p_mut.x2 = X1;
1832  PDesc->prpty_Data->p_mut.y2 = Y1;
1833  PDesc->prpty_Data->p_mut.coeff =
1834  ((union prp_data*)PDesc->prpty_Info)->p_mut.coeff;
1835  continue;
1836  }
1837  }
1838 }
1839 
1840 
1841 void
1843 
1844 /* look through the cell reference points. If any correspond to a
1845  * wire vertex that was just moved, transform the reference.
1846  */
1847 struct o *Pointer;
1848 long RefX,RefY;
1849 {
1850  struct prpty *PDesc;
1851  long X,Y;
1852 
1853  if (Pointer->oType != CDWIRE) return;
1854 
1855  PDesc = Parameters.kpCellDesc->sPrptyList;
1856  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1857  if (PDesc->prpty_Value != P_NODE) continue;
1858  X = PDesc->prpty_Data->p_node.x;
1859  Y = PDesc->prpty_Data->p_node.y;
1860  if (RefX == X && RefY == Y) {
1861  TPoint(&X,&Y);
1862  PDesc->prpty_Info = (char*)PDesc->prpty_Data;
1863  PDesc->prpty_Data = umalloc(prp_data);
1864  PDesc->prpty_Data->p_node.x = X;
1865  PDesc->prpty_Data->p_node.y = Y;
1866  PDesc->prpty_Data->p_node.enode =
1867  ((union prp_data*)PDesc->prpty_Info)->p_node.enode;
1868  PDesc->prpty_Data->p_node.inode =
1869  ((union prp_data*)PDesc->prpty_Info)->p_node.inode;
1870  }
1871  }
1872 }
1873 
1874 
1875 void
1877 
1878 {
1879  struct prpty *PDesc;
1880 
1881  PDesc = Parameters.kpCellDesc->sPrptyList;
1882  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1883  if (PDesc->prpty_Value != P_NODE) continue;
1884  if (PDesc->prpty_Info == NULL) continue;
1885  free(PDesc->prpty_Data);
1886  PDesc->prpty_Data = (union prp_data*)PDesc->prpty_Info;
1887  PDesc->prpty_Info = NULL;
1888  }
1889 }
1890 
1891 
1892 void
1894 
1895 {
1896  struct prpty *PDesc;
1897 
1898  PDesc = Parameters.kpCellDesc->sPrptyList;
1899  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1900  if (PDesc->prpty_Value != P_NODE) continue;
1901  if (PDesc->prpty_Info == NULL) continue;
1902  free(PDesc->prpty_Info);
1903  PDesc->prpty_Info = NULL;
1904  }
1905 }
1906 
1907 
1908 static int
1910 
1911 /* return True if X,Y are coordinates of a device or subcircuit terminal */
1912 long X,Y;
1913 {
1914  struct g *GenDesc;
1915  struct prpty *PDesc;
1916  struct o *Pointer;
1917  int Info;
1918 
1919  if (Not CDInitGen(Parameters.kpCellDesc,0,X,Y,X,Y,&GenDesc))
1920  MallocFailed();
1921 
1922  loop {
1923 
1924  CDGen(Parameters.kpCellDesc,GenDesc,&Pointer);
1925  if (Pointer == NULL) break;
1926  if (Pointer->oInfo == SQ_GONE) continue;
1927 
1928  PDesc = Pointer->oPrptyList;
1929  for (; PDesc; PDesc = PDesc->prpty_Succ) {
1930  if (PDesc->prpty_Value != P_NODE) continue;
1931  if (X == PDesc->prpty_Data->p_node.x &&
1932  Y == PDesc->prpty_Data->p_node.y) {
1933  tfree(GenDesc);
1934  return (True);
1935  }
1936  }
1937  }
1938  return (False);
1939 }
1940 
struct prpty * sPrptyList
Definition: cddefs.h:133
int li_linenum
Definition: fteinp.h:15
static void insert_terminal()
#define PL_ESC
Definition: sced.h:62
void ErasePrompt()
Definition: viewport.c:538
struct line * li_actual
Definition: fteinp.h:19
DISPDEVICE device[]
Definition: display.c:24
#define loop
Definition: cdmacs.h:11
void TPoint()
void Redisplay()
int struct o * Pointer
Definition: cd.c:1311
#define Or
Definition: cdmacs.h:15
int prpty_Value
Definition: cdprpty.h:67
char * prpty_Info
Definition: cdprpty.h:64
static int pType()
static void ww_free()
#define SQ_GONE
Definition: sced.h:347
int AreTypesInQ()
void AssignWireProperties(struct o *Pointer)
Definition: netlist.c:98
struct line * PrintMutual()
#define PL_UND
Definition: sced.h:63
int kpModified
Definition: sced.h:261
long kaRight
Definition: sced.h:112
int cieq()
#define CDINFINITY
Definition: cddefs.h:70
static void spice_deck_sort()
char * strcpy()
void HYfree()
Definition: cddefs.h:119
struct o * ksPointer
Definition: sced.h:335
void Subcircuit(int *LookedAhead)
Definition: netlist.c:1510
static int device_node()
static void set_device_node()
char * CopyString()
double kvFineRatio
Definition: sced.h:154
Definition: objects.c:1183
int PointLoop()
struct kc SCursor
Definition: init.c:21
char oType
Definition: cddefs.h:148
int enode
Definition: cdprpty.h:24
long kaBottom
Definition: sced.h:112
double kvCoarseRatio
Definition: sced.h:155
void ShowCurrentObject()
#define ERASE
Definition: scedmacs.h:11
#define Not
Definition: cdmacs.h:16
struct s * kpCellDesc
Definition: sced.h:207
void ConnectRecursive(struct s *CellDesc)
Definition: netlist.c:512
struct line * AllocateLine()
int x1
Definition: cdprpty.h:31
void DisplayTerminals(int DisplayOrErase)
Definition: netlist.c:1729
char * kpCellName
Definition: sced.h:210
static void change_wire_node()
static void renumber_wires()
int CDStatusInt
Definition: cd.c:75
static int is_wire_grounded()
struct prp_node p_node
Definition: cdprpty.h:52
#define P_MODEL
Definition: cdprpty.h:16
char * malloc()
#define PL_PCW
Definition: sced.h:65
struct ww * ww_next
Definition: netlist.c:479
int x
Definition: cdprpty.h:26
void CDGen()
#define CDPARSEFAILED
Definition: cddefs.h:27
int InBox()
static void global_modify()
Definition: netlist.c:1411
#define P_NODE
Definition: cdprpty.h:12
Definition: cddefs.h:169
void ShowProperties(int *LookedAhead)
Definition: netlist.c:1065
Definition: sced.h:111
static int prptyKB()
Definition: cddefs.h:312
#define P_VALUE
Definition: cdprpty.h:17
#define P_BRANCH
Definition: cdprpty.h:15
long kcY
Definition: sced.h:102
int CDOpen()
void CDWire()
static void connect_wire_to_device()
#define P_OTHER
Definition: cdprpty.h:19
Definition: cddefs.h:215
Definition: sced.h:193
#define alloc(type)
Definition: cdmacs.h:21
static void p_free()
void ShowPromptAndWait()
int x
Definition: cdprpty.h:39
void UpdateProperties(struct o *Pointer)
Definition: netlist.c:27
union prp_data * prpty_Data
Definition: cdprpty.h:65
long pY
Definition: cddefs.h:216
void DumpSpiceFile(FILE *fp)
Definition: netlist.c:162
int r2
Definition: cdprpty.h:42
struct hprlist * FBHyEdit()
char * tmalloc()
void MallocFailed()
Definition: scedintr.c:857
Definition: fteinp.h:14
#define CDSYMBOLCALL
Definition: cddefs.h:43
#define SQ_INCMPLT
Definition: sced.h:356
char * kpCommand
Definition: sced.h:219
long X
Definition: actions.c:450
static void set_wire_node()
void MenuDeselect()
Definition: cddefs.h:237
#define tfree(x)
Definition: cdmacs.h:22
int CDInitGen()
int CDAddProperty()
void txfree()
struct ks * ksSucc
Definition: sced.h:334
#define NULL
Definition: spdefs.h:121
char TypeOut[200]
Definition: init.c:23
struct kp Parameters
Definition: init.c:19
int y1
Definition: cdprpty.h:32
long kaTop
Definition: sced.h:112
long * InPath()
char * li_line
Definition: fteinp.h:16
void TransformReferences(struct o *Pointer)
Definition: netlist.c:1760
#define True
Definition: scedstub.c:16
short FBGetchar()
#define MARK_CROSS
Definition: scedmacs.h:18
char * mName
Definition: cddefs.h:111
#define P_INITC
Definition: cdprpty.h:18
struct kv * View
Definition: init.c:17
int kpShowTerminals
Definition: sced.h:255
static double c
Definition: vectors.c:16
char * MenuUNDO
Definition: scedintr.c:108
char * subname
Definition: cdprpty.h:48
char * MenuPRPTY
Definition: scedintr.c:97
void EraseBox()
int y2
Definition: cdprpty.h:34
struct line * li_next
Definition: fteinp.h:18
int SelectNode(long *Xo, long *Yo)
Definition: netlist.c:1624
void ClearReferenceUndoFlags()
Definition: netlist.c:1893
void SQDesel()
static void connect_ground_to_device()
struct o * oRep
Definition: cddefs.h:144
long kaLeft
Definition: sced.h:112
int y
Definition: cdprpty.h:27
#define DISPLAY
Definition: scedmacs.h:12
static int find_node()
void SQShow()
Definition: choose.c:940
Definition: cddefs.h:142
#define P_NAME
Definition: cdprpty.h:13
int y
Definition: cdprpty.h:40
void inp_deckfree()
static char model[32]
Definition: subckt.c:76
static void update_device(struct o *odesc, refcnts)
Definition: netlist.c:66
struct prp_branch p_branch
Definition: cdprpty.h:54
#define CDNEWSYMBOL
Definition: cddefs.h:29
qsort()
Definition: string.c:375
struct ks * SelectQHead
Definition: scedext.h:64
long pX
Definition: cddefs.h:216
Definition: cddefs.h:177
void SelectTypes()
int Layer
Definition: cd.c:1908
struct m * mSucc
Definition: cddefs.h:112
struct o * ww_ptr
Definition: netlist.c:478
#define CDWIRE
Definition: cddefs.h:47
#define P_MUT
Definition: cdprpty.h:14
return(True)
int num
Definition: cdprpty.h:47
struct line * MakeSpiceDeck()
Definition: netlist.c:183
int kpEnableSelectQRedisplay
Definition: sced.h:249
char * MenuTERMS
Definition: scedintr.c:107
void Connect(struct s *CellDesc)
Definition: netlist.c:539
Definition: netlist.c:477
void DoSpiceList()
Definition: netlist.c:132
struct line * SpiceList(struct s *CellDesc)
Definition: netlist.c:205
struct prpty * prpty_Succ
Definition: cdprpty.h:66
long kcX
Definition: sced.h:102
char * MenuSPICE
Definition: netlist.c:128
int r1
Definition: cdprpty.h:41
void ShowMarker()
Definition: sced.h:333
char * name
Definition: cdprpty.h:46
int CDBB()
int inode
Definition: cdprpty.h:25
void UndoReferenceTransform()
Definition: netlist.c:1876
int count
Definition: output.c:152
Definition: cddefs.h:227
struct line * PrintModels()
Definition: library.c:279
void QueueModel()
double coeff
Definition: cdprpty.h:35
#define False
Definition: scedstub.c:15
struct prp_name p_name
Definition: cdprpty.h:55
static int lcomp()
void ShowTerminals()
Definition: netlist.c:1710
#define PL_CMD
Definition: sced.h:64
int kcInFine
Definition: sced.h:105
int x2
Definition: cdprpty.h:33
#define umalloc(u)
Definition: netlist.c:17
int IsCellInLib()
#define ESCAPE
Definition: sced.h:91
Definition: cddefs.h:192
char * HYtostr()
void MenuSelect()
struct prp_mut p_mut
Definition: cdprpty.h:53
struct p * pSucc
Definition: cddefs.h:217
long Y
Definition: actions.c:450
static void connect_wires()
Definition: cdprpty.h:62
void TransformReferencePoint(struct o *Pointer, long RefX, long RefY)
Definition: netlist.c:1842
void ShowPrompt(char *str)
Definition: scedstub.c:71
Definition: cddefs.h:109
short oInfo
Definition: cddefs.h:147
char * trealloc()
static void connect_devices()
struct ka SelectQBB
Definition: scedext.h:65
struct prpty * oPrptyList
Definition: cddefs.h:146
void free()
void HYinit()
Definition: hypertxt.c:834
void SQComputeBB()
Definition: choose.c:749
#define HighlightingColor
Definition: sced.h:74
char * MenuSUBCT
Definition: scedintr.c:106
struct hprlist * HYcopy()