1 /****************************************************************************
2     Copyright (C) 1987-2015 by Jeffery P. Hansen
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
18     Last edit by hansen on Thu Feb 12 14:49:29 2009
19 ****************************************************************************/
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <sys/time.h>
25 #include <assert.h>
26 #include "tkgate.h"
27 
28 
29 static SHash *GateTypeHash = 0;		/* Map from new style gate type names to gateinfo */
30 static SHash *OldGateTypeHash = 0;	/* Map from old verilog name to gateinfo */
31 NHash *GateIdxHash = 0;			/* Map from gate type code to gateinfo */
32 Icon *INVERTER;				/* Icon for inverter buble */
33 Icon *Mark;				/* Icon for position mark */
34 Icon *SIZEHASH;				/* Icon for wire bit size hash mark */
35 Icon *REPCOUNTMARK;			/* Icon for replicate mark */
36 int GlobalElementCount = 0;		/* Global counter of gate elements */
37 
38 /*****************************************************************************
39  *
40  * Table for IO direction marks for pins on logic blocks.  Note, these arrows
41  * are also shared by concat elements.
42  *
43  *****************************************************************************/
44 static Icon *iodmark[4][4];	/* Normal arrows [orient][iodir] */
45 static Icon *boxmark[4][4];	/* Boxed arrows [orient][iodir] */
46 
47 /*****************************************************************************
48  *
49  * Set the name of a gate in a module
50  *
51  * Parameters:
52  *    g			Gate on which to change/set name.
53  *    name		New name for gate.
54  *    M			Module in which gate is defined (null if gate is not
55  *			yet in defined in a module).
56  *
57  *****************************************************************************/
gate_setName(GCElement * g,const char * name,GModuleDef * M)58 void gate_setName(GCElement *g,const char *name,GModuleDef *M)
59 {
60   char buf[1024];
61   SHash *H = M ? M->m_gates : 0;
62 
63   if (name && g->ename && strcmp(name,g->ename) == 0)
64     return;
65 
66   pickValidName(buf,name,"g",H);
67 
68   if (g->ename) {
69     SHash_remove(H,g->ename);
70     ob_free(g->ename);
71   }
72   ob_touch(g);
73   g->ename = ob_strdup(buf);
74   g->show_name = (name != 0);
75   if (H)
76     SHash_insert(H,g->ename,g);
77 }
78 
79 /*****************************************************************************
80  *
81  * Add a gate to a module.
82  *
83  * Parameters:
84  *    M			Module in which gate will be placed
85  *    g			Gate to be added.
86  *
87  *****************************************************************************/
gate_add(GModuleDef * M,GCElement * g)88 void gate_add(GModuleDef *M,GCElement *g)
89 {
90   if (!g->ename) {
91     ob_touch(g);
92     gate_setName(g,0,M);
93     g->show_name = 0;
94   }
95 }
96 
97 /*****************************************************************************
98  *
99  * Remove a gate from a module.
100  *
101  * Parameters:
102  *    M			Module in which gate is currently defined.
103  *    g			Gate to remove from module.
104  *
105  *****************************************************************************/
gate_remove(GModuleDef * M,GCElement * g)106 void gate_remove(GModuleDef *M,GCElement *g)
107 {
108   SHash_remove(M->m_gates,g->ename);
109 }
110 
111 /*****************************************************************************
112  *
113  * Creates a new gate object.
114  *
115  * Parameters:
116  *    x,y		Position for new gate.
117  *    rot		Initial rotation for new gate.
118  *    type		Type of new gate.
119  *
120  * Returns:		New gate object (not yet inserted into a module)
121  *
122  *****************************************************************************/
gate_new(int x,int y,int rot,int type)123 GCElement *gate_new(int x,int y,int rot,int type)
124 {
125   GGateInfo *ginfo = GGateInfo_codeLookup(type);
126   GCElement *g;
127   int i,n;
128   int N;
129 
130 #ifdef DEBUG
131   printf("gate_new(%d %d %d  NULL)\n",x,y,type);
132 #endif
133 
134   g = (GCElement *) ob_malloc(sizeof(GCElement)+requiredPortMemory(ginfo->NumPads),"GCElement");
135 
136   memset(g,0,sizeof(*g));
137 
138   g->typeinfo = ginfo;
139   g->tech = ob_strdup(TKGATE_DEFAULT_TECH);
140   g->xpos = x;
141   g->ypos = y;
142   g->top = 0;
143   g->bottom = 0;
144   g->selected = 0;
145   g->orient = g->typeinfo->Flags.CanRot ? rot : 0;
146   g->ename = 0;
147   g->show_name = 0;
148   g->anchored = 0;
149   g->cust_delay = 0;
150   g->isModuleInterface = 0;
151   g->cpath_cut = 0;
152   g->enumb = GlobalElementCount++;
153   N = GCElement_numPads(g);
154   for (i = 0;i < N;i++)
155     g->wires[i] = NULL;
156 
157   if (g->typeinfo->InitGate)
158     (*g->typeinfo->InitGate)(g);
159 
160   n = 0;
161   for (i = 0;g->typeinfo->delayNames[i];i++)n++;
162   if (n == 0)
163     g->delays = 0;
164   else {
165     g->delays = (int*) ob_malloc(sizeof(int)*n,"int[]");
166     for (i = 0;g->typeinfo->delayNames[i];i++)
167       g->delays[i] = 1;
168   }
169 
170   return g;
171 }
172 
173 /*****************************************************************************
174  *
175  * Unattach a wire from a gate.
176  *
177  * Parameters:
178  *    w			Wire to detach (gate is assumed)
179  *    M			Module in which wire is defined.
180  *    drawp		Non-zero if we should update the display after operation.
181  *
182  *****************************************************************************/
gate_unattachwire(GWire * w,GModuleDef * M,int drawp)183 void gate_unattachwire(GWire *w,GModuleDef *M,int drawp)
184 {
185   struct wire *wd;
186 
187   ob_touch(w);
188   ob_touch(w->gate);
189 
190   wd = w->driver;
191   if (M && drawp) GWire_draw(wd);
192   w->gate = NULL;
193   if (w->name) ob_free(w->name);
194 
195   w->name = NULL;
196 #if 0
197   if (!wire_trash(w->nodes,M,drawp)) {
198     w->invert = 0;
199     if (M && drawp) GWire_draw(wd);
200   } else {
201     if (M) {
202       ob_touch(M);
203       M->m_wires = wire_unlink(M->m_wires,w);
204     }
205     wire_free(w);
206   }
207 #else
208   if (!wire_nuke(w,drawp,M)) {
209     w->invert = 0;
210     if (M && drawp) GWire_draw(wd);
211   }
212 #endif
213 }
214 
215 /*****************************************************************************
216  *
217  * Unattach all wires from a pad of a gate.
218  *
219  * Parameters:
220  *    w			Head of pad list on a gate
221  *    M			Module in which to perform opreration
222  *    drawp		Non-zero if we should update display.
223  *
224  *****************************************************************************/
gate_unattachwirelist(GWire * w,GModuleDef * M,int drawp)225 void gate_unattachwirelist(GWire *w,GModuleDef *M,int drawp)
226 {
227   GWire *wnext;
228 
229   for (;w;w = wnext) {
230     wnext = w->next;
231     gate_unattachwire(w,M,drawp);
232   }
233 }
234 
235 /*****************************************************************************
236  *
237  * Cut all wires off of a gate.
238  *
239  * Parameters:
240  *    g			Gate to strip of all wires.
241  *    M			Module in which gate is defined/
242  *    drawp		Non-zero if we should update display.
243  *
244  *****************************************************************************/
gate_cutOffWires(GCElement * g,GModuleDef * M,int drawp)245 void gate_cutOffWires(GCElement *g,GModuleDef *M,int drawp)
246 {
247   int i;
248   int N = GCElement_numPads(g);
249 
250   ob_touch(g);
251   for (i = 0;i < N;i++) {
252     gate_unattachwirelist(g->wires[i],M,drawp);
253     g->wires[i] = NULL;
254   }
255 
256 }
257 
258 /*****************************************************************************
259  *
260  * Delete a gate.
261  *
262  * Parameters:
263  *    g			Gate to be deleted.
264  *    M			Module in which gate is currently defined.
265  *    drawp		Non-zero if we should update the display.
266  *
267  * Returns:		Non-zero on success.
268  *
269  * Delete a gate by unattaching all wires connected to it and removing it from
270  * the object list.  This function does not actually free the object.
271  *
272  *****************************************************************************/
gate_delete(GCElement * g,GModuleDef * M,int drawp)273 int gate_delete(GCElement *g,GModuleDef *M,int drawp)
274 {
275 #if 0
276   if (g->typeinfo != (void*)0xa7a7a7a7)
277     printf("gate_delete(%p: %s %s)\n",g,g->typeinfo->name,g->ename);
278   else {
279     printf("gate_delete(%p: bogus)\n",g);
280     abort();
281   }
282 #endif
283 
284   (*g->typeinfo->DeleteGate)(g,M,drawp);
285   ob_free(g);
286   /* g->typeinfo = 0; */
287 
288   return 1;
289 }
290 
291 /*****************************************************************************
292  *
293  * Auxilary function to do a hit test to detect a gate.
294  *
295  * Parameters:
296  *    x,y		Position of the "hit".
297  *    M			Module to search
298  *
299  * Returns:		The best gate for a hit at (x,y)
300  *
301  *****************************************************************************/
gate_hit(GModuleDef * M,int x,int y)302 GCElement *gate_hit(GModuleDef *M,int x,int y)
303 {
304   int threshDist = GATERANGE;
305   HashElem *gl;
306   GCElement *hit = 0;
307 
308   for (gl = Hash_first(M->m_gates);gl;gl = Hash_next(M->m_gates,gl)) {
309     GCElement *g = (GCElement*) HashElem_obj(gl);
310     int dist;
311 
312     dist = (*g->typeinfo->HitDistance)(g,x,y);
313 
314     if  (dist < threshDist) {
315       hit = g;
316       threshDist = dist;
317     }
318   }
319 
320   return hit;
321 }
322 
323 /*****************************************************************************
324  *
325  * Displays all the gates in a module
326  *
327  * Parameters:
328  *    M			Module to be displayed.
329  *
330  *****************************************************************************/
gate_displayall(GModuleDef * M)331 void gate_displayall(GModuleDef *M)
332 {
333   HashElem *gl;
334   GWireList *wl;
335 
336   for (gl = Hash_first(M->m_gates);gl;gl = Hash_next(M->m_gates,gl)) {
337     int MinX,MinY,MaxX,MaxY;
338     GCElement *g = (GCElement*) HashElem_obj(gl);
339 
340     gate_draw(g,GD_NOWIRE);
341     gate_getbbx(g,TD_X11,&MinX,&MinY,&MaxX,&MaxY);
342     if (MinX < TkGate.ed->min_x) TkGate.ed->min_x = MinX;
343     if (MinY < TkGate.ed->min_y) TkGate.ed->min_y = MinY;
344     if (MaxX > TkGate.ed->max_x) TkGate.ed->max_x = MaxX;
345     if (MaxY > TkGate.ed->max_y) TkGate.ed->max_y = MaxY;
346   }
347 
348   for (wl = M->m_wires;wl;wl = wl->wl_next) {
349     GWire *w = wl->wl_wire;
350     if (w == w->driver)
351       GWire_draw(w);
352   }
353 }
354 
355 /* Draws a gate (Circuit element) and the wires connected to it. */
gate_draw(GCElement * g,int md)356 void gate_draw(GCElement *g,int md)
357 {
358   if (g->typeinfo->DrawGate)
359     (*g->typeinfo->DrawGate)(g,md);
360   else
361     Generic_Draw(g,md);
362 }
363 
gate_drawWires(GCElement * g,int md)364 void gate_drawWires(GCElement *g,int md)
365 {
366   GWire *w;
367   int i;
368   int N = GCElement_numPads(g);
369 
370   if (md != GD_NOWIRE) {
371     for (i = 0;i < N;i++)
372       for (w = g->wires[i];w;w=w->next)
373 	if (w->nodes->out) {
374 	  GWire_draw(w);
375 	} else {
376 	  if ((w->driver->gate != g) && !(w->driver->gate && md == GD_NOINWIRE))
377 	    GWire_draw(w->driver);
378 	}
379   }
380 }
381 
gate_drawgatename(GCElement * g,const char * name)382 void gate_drawgatename(GCElement *g,const char *name)
383 {
384   int x,y;
385   int o;
386 
387   o = g->orient;
388   x = g->xpos;
389   y = g->ypos;
390 
391   if (g->selected)
392     XSetFont(TkGate.D,TkGate.instGC,TkGate.textbXF[TkGate.circuit->zoom_factor]->fid);
393   else
394     XSetFont(TkGate.D,TkGate.instGC,TkGate.textXF[TkGate.circuit->zoom_factor]->fid);
395 
396   dce_DrawString(TkGate.instGC,x + g->typeinfo->lpos[o].x,
397 		 y + g->typeinfo->lpos[o].y,
398 		 g->typeinfo->lpos[o].just,name);
399 }
400 
401 /* Moves a gate and adjusts wires */
gate_move(GCElement * g,int dx,int dy)402 void gate_move(GCElement *g,int dx,int dy)
403 {
404   if (GModuleDef_isDataProtected(TkGate.circuit->es->env)) {
405     message(0,msgLookup("err.protdata"));
406     return;
407   }
408 
409   if (g->anchored) {
410     message(0,msgLookup("err.gatanchor")); /* "Gate is anchored and can not be moved." */
411     return;
412   }
413 
414   SetModified(MF_NET|MF_GATE);
415 
416   (*g->typeinfo->MoveGate)(g,dx,dy);
417 }
418 
419 /*****************************************************************************
420  *
421  * Move an object by the specified amount (specified as a relative position)
422  *
423  *****************************************************************************/
gate_moveObject(GCElement * g,int dx,int dy)424 void gate_moveObject(GCElement *g,int dx,int dy)
425 {
426   if (g->anchored) {
427     message(0,msgLookup("err.gatanchor"));		/* "Gate is anchored and can not be moved." */
428     return;
429   }
430 
431   gate_draw(g,GD_NORMAL);
432   gate_move(g,dx,dy);
433   gate_draw(g,GD_NORMAL);
434 }
435 
gate_moveTo(GCElement * g,int x,int y)436 void gate_moveTo(GCElement *g,int x,int y)
437 {
438   gate_move(g,x-g->xpos,y-g->ypos);
439 }
440 
441 /* Marks a gate */
gate_mark(GCElement * g,int select)442 void gate_mark(GCElement *g,int select)
443 {
444   ob_touch(g);
445   g->selected = select;
446 }
447 
448 /*
449   Gets the bounding box of a gate.
450 */
gate_getbbx(GCElement * g,TargetDev_e target,int * minx,int * miny,int * maxx,int * maxy)451 void gate_getbbx(GCElement *g,TargetDev_e target, int *minx,int *miny,int *maxx,int *maxy)
452 {
453   (*g->typeinfo->GetExtents)(g, target, minx,miny,maxx,maxy,0);
454 }
455 
displayRepCount(int x,int y,int num)456 void displayRepCount(int x,int y,int num)
457 {
458   char ns[30];
459 
460   Icon_draw(TkGate.D,TkGate.W,TkGate.toolGC,ctow_x(x),ctow_y(y),REPCOUNTMARK);
461 
462   sprintf(ns,"%d",num);
463   dce_DrawString(TkGate.toolGC,x+10,y,BetweenTopAndBottom|AtLeft,ns);
464 }
465 
gate_doReplication(EditState * es)466 void gate_doReplication(EditState *es)
467 {
468   struct celemnt *g;
469   int sx,sy,ex,ey,dx,dy,h,w,n,bd,num;
470 
471   g = TkGate.circuit->select;
472   ZDrawLine(TkGate.D,TkGate.W,TkGate.toolGC,ctow_x(TkGate.ed->sx),ctow_y(TkGate.ed->sy),ctow_x(TkGate.ed->tx),ctow_y(TkGate.ed->ty));
473 
474   (*g->typeinfo->GetExtents)(g,TD_X11,&sx,&sy,&ex,&ey,&bd);
475 
476   w = ex-sx + bd;
477   h = ey-sy + bd;
478 
479   sx = g->xpos;
480   sy = g->ypos;
481   ex = TkGate.ed->tx;
482   ey = TkGate.ed->ty;
483 
484   if (sx == ex) {
485     dx = 0;
486     dy = (sy > ey) ? -h : h;
487     n = abs((sy-ey)/dy);
488   } else if (sy == ey) {
489     dx = (sx > ex) ? -w : w;
490     dy = 0;
491     n = abs((sx-ex)/dx);
492   } else if (abs(10*(sy-ey)/(sx-ex)) > (10*h)/w) {
493     dy = (sy > ey) ? -h : h;
494     dx = (dy*(sx-ex))/(sy-ey);
495     n = abs((sy-ey)/dy);
496   } else {
497     dx = (sx > ex) ?-w : w;
498     dy = (dx*(sy-ey))/(sx-ex);
499     n = abs((sx-ex)/dx);
500   }
501 
502   sx += dx;
503   sy += dy;
504   num = 2;
505   while (n--) {
506     GCElement *ng;
507 
508     displayRepCount(sx,sy,num);
509     ng = (*g->typeinfo->CopyGate)(es->env,g,sx,sy,0);
510     gate_draw(ng,0);
511     sx += dx;
512     sy += dy;
513     num++;
514   }
515 }
516 
gate_setinvertwirelist(GWire * nw,GWire * w)517 void gate_setinvertwirelist(GWire *nw,GWire *w)
518 {
519   for (;nw && w;w = w->next,nw = nw->next) {
520     ob_touch(nw);
521     nw->invert = w->invert;
522   }
523 }
524 
gate_hashrepline(EditState * es,int x,int y)525 void gate_hashrepline(EditState *es,int x,int y)
526 {
527   GCElement *g;
528   int sx,sy,ex,ey,dx,dy,bd,h,w,n,num;
529 
530   g = TkGate.circuit->select;
531 
532   (*g->typeinfo->GetExtents)(g,TD_X11,&sx,&sy,&ex,&ey,&bd);
533 
534   w = ex-sx + bd;
535   h = ey-sy + bd;
536 
537   sx = g->xpos;
538   sy = g->ypos;
539   ex = x;
540   ey = y;
541 
542   if (sx == ex) {
543     dx = 0;
544     dy = (sy > ey) ? -h : h;
545     n = abs((sy-ey)/dy);
546   } else if (sy == ey) {
547     dx = (sx > ex) ? -w : w;
548     dy = 0;
549     n = abs((sx-ex)/dx);
550   } else if (abs(10*(sy-ey)/(sx-ex)) > (10*h)/w) {
551     dy = (sy > ey) ? -h : h;
552     dx = (dy*(sx-ex))/(sy-ey);
553     n = abs((sy-ey)/dy);
554   } else {
555     dx = (sx > ex) ? -w : w;
556     dy = (dx*(sy-ey))/(sx-ex);
557     n = abs((sx-ex)/dx);
558   }
559 
560   sx += dx;
561   sy += dy;
562   num = 2;
563   while (n--) {
564     displayRepCount(sx,sy,num);
565     sx += dx;
566     sy += dy;
567     num++;
568   }
569 }
570 
GGateInfo_getPadNum(GGateInfo * gi,const char * pname)571 int GGateInfo_getPadNum(GGateInfo *gi,const char *pname)
572 {
573   char buf[STRMAX];
574   int p;
575 
576   if (sscanf(pname,"%[A-Za-z]",buf) != 1)
577     return -1;
578 
579   for (p = 0;p < gi->NumPads;p++)
580     if (strcmp(gi->Pad[p].name,buf) == 0)
581       return p;
582 
583   return -1;
584 }
585 
586 /*
587    Transmute a gate from one type to another.
588 
589    Warning: Only certain types of transmutations can be
590    performed.
591 */
gate_transmute(GCElement * g,GGateInfo * ngi)592 void gate_transmute(GCElement *g,GGateInfo *ngi)
593 {
594   GGateInfo *ogi = g->typeinfo;
595   int oldOrient,rot,i;
596 
597   assert(ngi->NumPads == ogi->NumPads);
598 
599   ob_touch(g);
600 
601   oldOrient = g->orient;
602   rot = ogi->Pad[0].Loc[oldOrient].dir;
603   for (i = 0;i < 4;i++)
604     if (ngi->Pad[0].Loc[i].dir == rot) {
605       g->orient = i;
606       break;
607     }
608   assert(i != 4);
609 
610   for (i = 0;i < ngi->NumPads;i++) {
611     GWire *w;
612     GPadLoc *oL = &ogi->Pad[i].Loc[oldOrient];
613     GPadLoc *nL = &ngi->Pad[i].Loc[g->orient];
614 
615     for (w = g->wires[i];w;w = w->next) {
616       ob_touch(w->nodes);
617       w->nodes->x += nL->x1 - oL->x1;
618       w->nodes->y += nL->y1 - oL->y1;
619     }
620   }
621 
622   g->typeinfo = ngi;
623 }
624 
625 /*****************************************************************************
626  *
627  * Get number of pads on a gate.
628  *
629  * Paramaters:
630  *     g		Gate to examine for pad count
631  *
632  * Returns:		Number of pads on g
633  *
634  * Return the number of pads on a gate.  For all gate types except symbol
635  * modules we get this from the gate's typeinfo object.  For symbol modules,
636  * we use the symbol data.
637  *
638  *****************************************************************************/
GCElement_numPads(GCElement * g)639 int GCElement_numPads(GCElement *g)
640 {
641   extern GGateInfo gate_symblock_info;
642 
643   if (g->typeinfo == &gate_symblock_info) {
644     if (g->u.block.symbol)
645       return GModSymbol_numPorts(g->u.block.symbol);
646     else
647       return 0;
648   } else
649     return g->typeinfo->NumPads;
650 }
651 
GCElement_getPadLoc(GCElement * g,int p,int r)652 GPadLoc *GCElement_getPadLoc(GCElement *g,int p,int r)
653 {
654   extern GGateInfo gate_symblock_info;
655 
656   if (g->typeinfo == &gate_symblock_info) {
657     GSymPort *sp = GModSymbol_getPort(g->u.block.symbol,p);
658     return &sp->msp_loc[r];
659   } else
660     return &g->typeinfo->Pad[p].Loc[r];
661 }
662 
GCElement_getPadDir(GCElement * g,int p)663 int GCElement_getPadDir(GCElement *g,int p)
664 {
665   extern GGateInfo gate_symblock_info;
666 
667   if (g->typeinfo == &gate_symblock_info) {
668     GSymPort *sp = GModSymbol_getPort(g->u.block.symbol,p);
669     return sp->msp_type;
670   } else
671     return g->typeinfo->Pad[p].iotype;
672 }
673 
674 /*****************************************************************************
675  *
676  * Get the name of the pth pad.
677  *
678  * Parameters:
679  *      g		Gate in on which we are looking up the pad name.
680  *      p		Index of pad
681  *
682  *****************************************************************************/
GCElement_getPadName(GCElement * g,int p)683 const char *GCElement_getPadName(GCElement *g,int p)
684 {
685   extern GGateInfo gate_symblock_info;
686 
687   if (g->typeinfo == &gate_symblock_info) {
688     GSymPort *sp = GModSymbol_getPort(g->u.block.symbol,p);
689     return sp->msp_name;
690   } else
691     return g->typeinfo->Pad[p].name;
692 }
693 
694 /*****************************************************************************
695  *
696  * Get the wire associated with the named pad on a gate
697  *
698  * Parameters:
699  *      g		Gate
700  *      portName	Index of pad
701  *
702  *****************************************************************************/
GCElement_getPort(GCElement * g,const char * portName)703 GWire *GCElement_getPort(GCElement *g, const char *portName)
704 {
705   int n = GCElement_numPads(g);
706   GWire *w;
707   int i;
708 
709   if (GCElement_getType(g) == GC_BLOCK) {
710     for (i = 0;i < n;i++)
711       for (w = g->wires[i];w;w = w->next)
712 	if (strcmp(w->name,portName) == 0)
713 	  return w;
714   } else if (GCElement_getType(g) == GC_SYMBLOCK) {
715     for (i = 0;i < n;i++) {
716       GSymPort *sp = GModSymbol_getPort(g->u.block.symbol,i);
717       if (strcmp(sp->msp_name, portName) == 0)
718 	return g->wires[i];
719     }
720   } else {
721     GGateInfo *gi = g->typeinfo;
722     int k = 0;
723 
724     i = GGateInfo_getPadNum(gi,portName);
725     if (sscanf(portName+strlen(gi->Pad[i].name),"%d",&k) != 1) k = 0;
726 
727     for (w = g->wires[i];k > 0 && w;w = w->next, k--);
728     return w;
729   }
730   return 0;
731 }
732 
GCElement_getPadCanAdd(GCElement * g,int p)733 int GCElement_getPadCanAdd(GCElement *g,int p)
734 {
735   extern GGateInfo gate_symblock_info;
736 
737   if (g->typeinfo == &gate_symblock_info) {
738     return 0;
739   } else
740     return g->typeinfo->Pad[p].CanAdd;
741 }
742 
743 /*****************************************************************************
744  *
745  * Set the symbol to use for a symbol block module.
746  *
747  * Parameters:
748  *      g		Gate on which to set symbol (must be a SYMBLOCK)
749  *      ms		Symbol to set for gate.
750  *
751  *****************************************************************************/
GCElement_setSymbol(GCElement * g,GModSymbol * ms)752 void GCElement_setSymbol(GCElement *g, GModSymbol *ms)
753 {
754   ob_touch(g);
755   if (g->u.block.symbol) {
756     GModSymbol_detach(g->u.block.symbol);
757   }
758   g->u.block.symbol = ms;
759   if (ms) {
760     GModSymbol_attach(ms);
761   }
762 }
763 
764 /*****************************************************************************
765  *
766  * Lookup function for new-style gate type names.
767  *
768  * Parameters:
769  *    name		Name to look up.
770  *
771  * Returns:		Gate info object corresponding to name
772  *
773  *****************************************************************************/
GGateInfo_lookup(const char * name)774 GGateInfo *GGateInfo_lookup(const char *name)
775 {
776   return (GGateInfo*) SHash_find(GateTypeHash,name);
777 }
778 
779 /*****************************************************************************
780  *
781  * Lookup function for old-style gate type names.
782  *
783  * Parameters:
784  *    name		Name to look up.
785  *
786  * Returns:		Gate info object corresponding to name
787  *
788  *****************************************************************************/
GGateInfo_vlookup(const char * name)789 GGateInfo *GGateInfo_vlookup(const char *name)
790 {
791   return (GGateInfo*) SHash_find(OldGateTypeHash,name);
792 }
793 
794 /*****************************************************************************
795  *
796  * Lookup function for old-style gate type variant numbers.
797  *
798  * Parameters:
799  *    gi		Gate info for gate type.
800  *    name		Name to look up.
801  *
802  * Returns:		Variant number corresponding to name.
803  *
804  *****************************************************************************/
GGateInfo_variantNum(GGateInfo * gi,const char * func)805 int GGateInfo_variantNum(GGateInfo *gi,const char *func)
806 {
807   int vn = 0;
808   char *p;
809   int L = strlen(func);
810 
811   for (p = gi->vnames;p && *p;vn++,p = strchr(p+1,':')) {
812     if (*p == ':') p++;
813     if (strncmp(p,func,L) == 0 && (p[L] == ':' || !p[L]))
814       break;
815   }
816 
817   return vn;
818 }
819 
820 /*****************************************************************************
821  *
822  * Registers a gate type
823  *
824  * Parameters:
825  *    gi		Gate info object to be registered.
826  *
827  *****************************************************************************/
RegisterGate(GGateInfo * gi)828 void RegisterGate(GGateInfo *gi)
829 {
830   static int code_count = 1;
831   char buf[STRMAX],*T;
832 
833   if (gi->code <= 0)
834     gi->code = code_count++;
835 
836   if (!gi->vnames) {
837     fprintf(stderr,"No verilog name for block '%s'\n",gi->name);
838     exit(1);
839   }
840   strcpy(buf,gi->vnames);
841 
842   for (T = strtok(buf,":");T;T = strtok(0,":")) {
843     SHash_insert(OldGateTypeHash,T,gi);
844   }
845 
846   SHash_insert(GateTypeHash,gi->name,gi);
847   NHash_insert(GateIdxHash,gi->code,gi);
848 }
849 
850 /*****************************************************************************
851  *
852  * Initialize special icons if we are running in interactive mode.
853  *
854  *****************************************************************************/
init_specials(void)855 void init_specials(void)
856 {
857   if (TkGate.tcl) {
858     Pixmap P;
859     Icon *ico;
860 
861     P = Pixmap_registerFromFile("misc","misc.b");
862     Mark = new_Icon(P,6,28,9,9,4,4);
863     SIZEHASH = new_Icon(P,16,27,10,10,4,4);
864     INVERTER = new_Icon(P,0,28,5,5,2,2);
865     REPCOUNTMARK = new_Icon(P,32,0,9,9,4,4);
866 
867     /*****************************************************************************
868      * Register pixmaps for arrows
869      *****************************************************************************/
870     P = Pixmap_registerFromFile("iodarrow","iodarrow.b");
871 
872     ico = new_Icon(P,14,0,7,5,3,2);	/* <> arrow */
873     iodmark[0][TRI] = iodmark[2][TRI] = ico;
874 
875     ico = new_Icon(P,14,6,5,7,2,3);	/* v^ arrow */
876     iodmark[1][TRI] = iodmark[3][TRI] = ico;
877 
878     ico = new_Icon(P,22,0,5,5,2,2);   /* x mark */
879     iodmark[0][ANY] = iodmark[1][ANY] = iodmark[2][ANY] = iodmark[3][ANY] = ico;
880 
881     ico = new_Icon(P,0,0,7,5,2,3);   /* < arrow */
882     iodmark[0][IN] = iodmark[2][OUT] = ico;
883 
884     ico = new_Icon(P,6,8,7,5,3,2);   /* > arrow */
885     iodmark[0][OUT] = iodmark[2][IN] = ico;
886 
887     ico = new_Icon(P,8,0,5,7,2,3);   /* v arrow */
888     iodmark[1][IN] = iodmark[3][OUT] = ico;
889 
890     ico = new_Icon(P,0,6,5,7,2,3);   /* ^ arrow */
891     iodmark[1][OUT] = iodmark[3][IN] = ico;
892 
893 
894 
895     /*****************************************************************************
896      * Register pixmaps for boxed arrows
897      *****************************************************************************/
898     P = Pixmap_registerFromFile("boxarrow","boxarrow.b");
899 
900     ico = new_Icon(P,24,0,11,11,5,5);	/* <> arrow */
901     boxmark[0][ANY] = boxmark[0][TRI] = boxmark[2][ANY] = boxmark[2][TRI] = ico;
902 
903     ico = new_Icon(P,24,12,11,11,5,5);	/* v^ arrow */
904     boxmark[1][ANY] = boxmark[1][TRI] = boxmark[3][ANY] = boxmark[3][TRI] = ico;
905 
906     ico = new_Icon(P,0,0,11,11,5,5);   /* < arrow */
907     boxmark[0][IN] = boxmark[2][OUT] = ico;
908 
909     ico = new_Icon(P,12,0,11,11,5,5);   /* > arrow */
910     boxmark[0][OUT] = boxmark[2][IN] = ico;
911 
912     ico = new_Icon(P,12,12,11,11,5,5);   /* v arrow */
913     boxmark[1][IN] = boxmark[3][OUT] = ico;
914 
915     ico = new_Icon(P,0,12,11,11,5,5);   /* ^ arrow */
916     boxmark[1][OUT] = boxmark[3][IN] = ico;
917 
918   }
919 }
920 
921 /*****************************************************************************
922  *
923  * Make the basic gate type info hash tables and initialize special objects
924  *
925  *****************************************************************************/
init_gateHashTables(void)926 void init_gateHashTables(void)
927 {
928   GateTypeHash = new_SHash();
929   OldGateTypeHash = new_SHash();
930   GateIdxHash = new_SHash();
931 }
932 
933 /*****************************************************************************
934  *
935  * Lookup the gate info object from a type code
936  *
937  * Parameters:
938  *    T			Type code to translate to a gate info object.
939  *
940  *****************************************************************************/
GGateInfo_codeLookup(int T)941 GGateInfo *GGateInfo_codeLookup(int T)
942 {
943   return (GGateInfo*) NHash_find(GateIdxHash,T);
944 }
945 
946 /*****************************************************************************
947  *
948  * Generate type name for primitive of a particular gate type.
949  *
950  * Parameters:
951  *    buf		Buffer to write type name to.
952  *    g			Gate from which to generate a type.
953  *
954  * Built-in tkgate modules have a special naming convension.  Here is
955  * an example:
956  *
957  * _GGNAND3B4D5 g1 (.Z(w1), .I0({{4}{w2}}), .I1(w3), .I2(w4));
958  *
959  * Here _GG is the prefix for built-in gates, the next "N" means that the
960  * output is inverted, "AND" is the base name of the gate, "3" indicates
961  * the number of inputs (or outputs depending on type), "B4" indicates the
962  * base bit width and "D5" indicates the delay of the gate.
963  *
964  * The general format is:
965  *
966  * _GG<inv><base-name><numport>x<bits><delay><parms>
967  *
968  * The meanings of the parts are:
969  *
970  *    <inv>		Output inverter state.  A single leading "N" means
971  *			that all outputs are inverted.  If this field is
972  *			omitted it means that all outputs are non-inverted.
973  *			For all other cases a string such as "NPPNN_" is used
974  *			to indicate the inverter status of each output port.
975  *
976  *    <base-name>	This is the base name of the element.  It must be one
977  *			of the tkgate defined primitive names.
978  *
979  *    <numport>		For primitives that have a variable number of ports on
980  *			one of their pads, this is the port count.  This field
981  *                      is omitted if the primitive has a fixed number of ports.
982  *
983  *    <bits>		This is the bit width of the gate if there are multiple
984  *			bit widths and the bit width is greater than 1.  Note
985  *			that if the <numport> field was omitted, the "x" preceeding
986  *			this field is omitted.
987  *
988  *    <delay>		A delay specification prefixed by "_D" if explicit values
989  *			are given, by "_T" if a technology is given or omitted
990  *			if from the default technology.
991  *
992  *    <parms>		If a gate has parameters, this string encodes the parameter
993  *			values beginning with a _P.
994  *
995  * Examples:
996  *
997  *   _GGNAND3x4_D5	3-input 4-bit wide AND gate with inverted output and
998  *			delay of 5.
999  *
1000  *   _GGOR4x8		4-input 8-bit wide OR gate with standard delay.
1001  *
1002  *   _GGOR4x8_Tmytech	4-input 8-bit wide OR gate with delay from "mytech".
1003  *
1004  *   _GGADD8_D68_70_62_64	8-bit adder with custom delay parameters of 68, 70, 62 and 64.
1005  *
1006  *   _GGCLOCK_P100_0_50	Clock with pulsewidth of 100, phase of 0 and duty cycle of 50.
1007  *
1008  * Specical case examples:
1009  *
1010  *   _GGRAM8x16		Ram with 8-bit address line and 16-bit data line.
1011  *
1012  *
1013  *****************************************************************************/
GGateInfo_encodeTypeName(char * buf,GCElement * g)1014 void GGateInfo_encodeTypeName(char *buf,GCElement *g)
1015 {
1016   GGateInfo *gi = g->typeinfo;
1017   int npad,nbit;
1018   char inv[STRMAX],*iq;
1019   unsigned inv_flags = 0;
1020   char *p;
1021   int i;
1022 
1023   /*
1024    * Get number of bits (or -1) if this gate has constant bit size.
1025    */
1026   if (gi->gi_bitPad >= 0) {
1027     GWire *w;
1028     nbit = 0;
1029     for (w = g->wires[gi->gi_bitPad];w;w = w->next)
1030       if (nbit < w->net->n_nbits)
1031 	nbit = w->net->n_nbits;
1032   } else
1033     nbit = -1;
1034 
1035   /*
1036    * Get port count variable for gate (or -1 if port count is fixed)
1037    */
1038   if (gi->gi_multiPad >= 0) {
1039     GWire *w;
1040     npad = 0;
1041     for (w = g->wires[gi->gi_multiPad];w;w = w->next) npad++;
1042   } else
1043     npad = -1;
1044 
1045   /*
1046    * Genrate standard prefix
1047    */
1048   p = buf;
1049   p += sprintf(p,"%s",TkGate.circuit->c_gatePrefix);
1050 
1051   /*
1052    * Generate output inverter sequence.
1053    */
1054   iq = inv;
1055   inv_flags = 0;
1056   for (i = 0;i < gi->NumPads;i++) {
1057     if (gi->Pad[i].iotype != IN) {
1058       GWire *w;
1059       for (w = g->wires[i];w;w = w->next) {
1060 	if (w->invert) {
1061 	  *iq++ = 'N';
1062 	  inv_flags |= 1;
1063 	} else {
1064 	  *iq++ = 'P';
1065 	  inv_flags |= 2;
1066 	}
1067       }
1068     }
1069   }
1070   *iq = 0;
1071   if (inv_flags == 1)
1072     p += sprintf(p,"N");		/* All outputs inverted, just attach an N */
1073   else if (inv_flags == 3)
1074     p += sprintf(p,"%s_",inv);		/* Mixed inverted and non-inverted outputs */
1075 
1076   /*
1077    * Generate gate base name
1078    */
1079   p += sprintf(p,"%s",gi->name);
1080 
1081 
1082   /*
1083    * Gate type specific modifictions.  Eventually this should function should be
1084    * made into a a gateinfo "virtual" function.
1085    */
1086   if (strcmp(gi->name,"RAM") == 0 || strcmp(gi->name,"ROM") == 0) {
1087     npad = g->wires[0]->net->n_nbits;	/* Address line bits */
1088     nbit = g->wires[1]->net->n_nbits;	/* Data line bits */
1089   }
1090 
1091   /*
1092    * Generate number of ports and bits
1093    */
1094   if (npad >= 0) p += sprintf(p,"%u",npad);
1095   if (nbit > 1) {
1096     if (npad >= 0)
1097       p += sprintf(p,"x%u",nbit);
1098     else
1099       p += sprintf(p,"%u",nbit);
1100   }
1101 
1102   /*
1103    * Generate delay codes
1104    */
1105 #if 0
1106   if (g->cust_delay) {
1107     for (i = 0;gi->delayNames[i];i++) {
1108       if (i == 0)
1109 	p += sprintf(p,"_D");
1110       else
1111 	p += sprintf(p,"_");
1112       p += sprintf(p,"%u",g->delays[i]);
1113     }
1114   } else {
1115     if (strcmp(g->tech,TKGATE_DEFAULT_TECH) != 0)
1116       p += sprintf(p,"_T%s",g->tech);
1117   }
1118 #endif
1119 
1120   /*
1121    * Gate type specific modifictions.  Eventually this should be moved into
1122    * a gateinfo function.
1123    */
1124   if (strcmp(gi->name,"CLOCK") == 0) {
1125     p += sprintf(p,"_P%u_%u_%u",g->u.clock.omega,g->u.clock.phi,g->u.clock.duty);
1126   }
1127 }
1128 
1129 /*****************************************************************************
1130  *
1131  * Decode a gate name and return non-zero if it is a built-in type.
1132  *
1133  * Parameters:
1134  *    name			Name of cell from verilog file
1135  *    gcs			Special structure with cell name decoding.
1136  *
1137  * Returns:			Non-zero if cell name was decoded.
1138  *
1139  *
1140  *****************************************************************************/
GGateInfo_decodeTypeName(const char * name,GCellSpec * gcs)1141 int GGateInfo_decodeTypeName(const char *name,GCellSpec *gcs)
1142 {
1143   char baseName[STRMAX];
1144   char dpSpec[STRMAX];		/* Delay an parameter specifications */
1145   int len = strlen(TkGate.circuit->c_gatePrefix);
1146   int n1,n2,i;
1147   int has_multipad = 0;
1148   int what;
1149   char *t;
1150 
1151   strcpy(gcs->gc_name,name);
1152 
1153   /*
1154    * If we don't have the right prefix, quite right now.
1155    */
1156   if (strncmp(name,TkGate.circuit->c_gatePrefix,len) != 0)
1157     return 0;
1158 
1159   /*
1160    * Advance past prefix and look for a complex inverter specification.
1161    */
1162   name += len;
1163   if (sscanf(name,"%[NP]_%s",gcs->gc_invSpec,baseName) == 2) {
1164     name += strlen(gcs->gc_invSpec)+1;
1165   } else
1166     *gcs->gc_invSpec = 0;		/* Normal or no inverter spec */
1167 
1168   /*
1169    * Copy prefix stripped name
1170    */
1171   if (sscanf(name,"%[A-Za-z]%dx%d_%s",baseName,&n1,&n2,dpSpec) == 4) {
1172   } else if (sscanf(name,"%[A-Za-z]%d_%s",baseName,&n1,dpSpec) == 3) {
1173     n2 = -1;
1174   } else if (sscanf(name,"%[A-Za-z]_%s",baseName,dpSpec) == 2) {
1175     n1 = n2 = -1;
1176   } else if (sscanf(name,"%[A-Za-z]%dx%d",baseName,&n1,&n2) == 3) {
1177     *dpSpec = 0;
1178   } else if (sscanf(name,"%[A-Za-z]%d",baseName,&n1) == 2) {
1179     *dpSpec = 0;
1180     n2 = -1;
1181   } else if (sscanf(name,"%[A-Za-z]",baseName) == 1) {
1182     *dpSpec = 0;
1183     n1 = n2 = -1;
1184   } else
1185     return 0;	/* Can not decode gate type name */
1186 
1187   /*
1188    * Try to look up the gate type, if we do not find it, see if it has a leading N.
1189    */
1190   gcs->gc_info = GGateInfo_lookup(baseName);
1191   if (!gcs->gc_info && *baseName == 'N' && !*gcs->gc_invSpec) {
1192     gcs->gc_info = GGateInfo_lookup(baseName+1);
1193     strcpy(gcs->gc_invSpec,"N");
1194   }
1195   if (!gcs->gc_info) return 0;
1196 
1197   /*
1198    * Test to see if we have a multi-port on this type
1199    */
1200   for (i = 0;i < gcs->gc_info->NumPads;i++)
1201     if (gcs->gc_info->Pad[i].CanAdd) {
1202       has_multipad = 1;
1203       break;
1204     }
1205 
1206   /*
1207    * If the gate has a "multipad" or it is a ROM or a RAM use n1 for the multi-pad size
1208    * and n2 for the bit size.  In all other cases there is no multipad and we use n1
1209    * for the number of bits.
1210    */
1211   if (has_multipad || strcmp(gcs->gc_info->name,"ROM") == 0 || strcmp(gcs->gc_info->name,"RAM") == 0) {
1212     gcs->gc_multiPad = n1;
1213     gcs->gc_numBits = n2;
1214   } else {
1215     gcs->gc_multiPad = -1;
1216     gcs->gc_numBits = n1;
1217   }
1218   if (gcs->gc_numBits < 0) gcs->gc_numBits = 1;
1219 
1220   /*
1221    * Initialize the delay and parameter arrays.
1222    */
1223   gcs->gc_numParms = 0;
1224   for (i = 0;i < MAXPARMS;i++) {
1225     gcs->gc_parms[i] = 1;
1226   }
1227 
1228 #if 0
1229   gcs->gc_numDelays = 0;
1230   for (i = 0;gcs->gc_info->delayNames[i];i++) {
1231     gcs->gc_delays[i] = 1;
1232   }
1233 #endif
1234 
1235 #if 1
1236   /*
1237    * Parse delay and parameter section.
1238    */
1239   what = 0;
1240   for (t = strtok(dpSpec,"_");t;t = strtok(0,"_")) {
1241     if (isalpha(*t))
1242       what = *t++;
1243 
1244     switch (what) {
1245 #if 0
1246     case 'D' :
1247       if (gcs->gc_numDelays >= MAXDELAYS) break;
1248       if (sscanf(t,"%d",&n1) == 1)
1249 	gcs->gc_delays[gcs->gc_numDelays++] = n1;
1250       break;
1251     case 'T' :
1252       {
1253 	GDelayDef *dd;
1254 
1255 	dd = GDelayDef_findTech(gcs->gc_info->delay_defs, t);
1256 	if (!dd) break;
1257 	gcs->gc_numDelays = GDelayDef_getDelaysFromCell(dd, gcs, gcs->gc_delays);
1258       }
1259       break;
1260 #endif
1261     case 'P' :
1262       if (gcs->gc_numParms >= MAXPARMS) break;
1263       if (sscanf(t,"%d",&n1) == 1)
1264 	gcs->gc_parms[gcs->gc_numParms++] = n1;
1265       break;
1266     }
1267   }
1268 #endif
1269 
1270   return 1;
1271 }
1272 
1273 /*****************************************************************************
1274  *
1275  * Get icon data for displaying a directional arrow.
1276  *
1277  *****************************************************************************/
GetPinIOMark(GWire * w,int d,int iod,int atype,int * x,int * y,Icon ** arrow)1278 void GetPinIOMark(GWire *w,int d,int iod,int atype,int *x,int *y,Icon **arrow)
1279 {
1280   int dx,dy;
1281 
1282   *x = w->nodes->x;
1283   *y = w->nodes->y;
1284 
1285   switch (atype) {
1286   case IODT_PORT :
1287     *arrow = iodmark[d][iod];
1288     dx = 4;
1289     dy = 5;
1290     break;
1291   case IODT_PLAIN :
1292     *arrow = iodmark[d][iod];
1293     dx = 8;
1294     dy = 5;
1295     break;
1296   //case IODT_BOXED :
1297   default:
1298     *arrow = boxmark[d][iod];
1299     dx = 12;
1300     dy = 7;
1301     break;
1302   }
1303 
1304   switch (d) {
1305   case D_UP :
1306     *x += dx;
1307     *y -= dy;
1308     break;
1309   case D_DOWN :
1310     *x += dx;
1311     *y += dy;
1312     break;
1313   case D_LEFT :
1314     *x -= dy;
1315     *y += dx;
1316     break;
1317   case D_RIGHT :
1318     *x += dy;
1319     *y += dx;
1320     break;
1321   }
1322 }
1323 
DrawPinIOMark(GWire * w,int d,int iod,int atype)1324 void DrawPinIOMark(GWire *w,int d,int iod,int atype)
1325 {
1326   int x,y;
1327   Icon *arrow;
1328   GC gc;
1329 
1330   if (atype == IODT_PORT)
1331     gc = TkGate.modportGC;
1332   else
1333     gc = TkGate.instGC;
1334 
1335   GetPinIOMark(w,d,iod,atype,&x,&y,&arrow);
1336   Icon_draw(TkGate.D,TkGate.W,gc,ctow_x(x),ctow_y(y),arrow);
1337 }
1338