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