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 Tue May  5 20:53:56 2009
19 ****************************************************************************/
20 
21 #ifdef __cplusplus
22 #include <cstdlib>
23 #include <cstdio>
24 #include <cassert>
25 #include <cstring>
26 #else
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <assert.h>
30 #include <string.h>
31 #endif
32 
33 #include <pwd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 
37 #include "tkgate.h"
38 #include "print.h"
39 
readprintcapentry(char * buf,int N,FILE * f)40 char *readprintcapentry(char *buf,int N,FILE *f)
41 {
42   char *p,*q;
43   int l;
44 
45   for (;;) {
46     p = buf;
47     for (;;) {
48       if (!fgets(p,N-(p-buf),f)) return 0;
49       q = strrchr(p,'\n');
50       if (q) *q = 0;
51       l = strlen(p);
52       if (l > 0 && p[l-1] == '\\') {
53 	p += l-1;
54       } else
55 	break;
56     }
57     for (p = buf;*p && strchr(" \t",*p);p++);
58     if (*p == '#' || *p == 0) continue;
59 
60     return buf;
61   }
62   return 0;
63 }
64 
65 /*
66   Check to see if modifications are OK, and if not issue a message.
67  */
modifyOK(EditState * es,unsigned flags)68 int modifyOK(EditState *es,unsigned flags)
69 {
70   if (!(flags & 0x2) && es->isInterface) {
71     message(0,msgLookup("err.badeditop"));	/* Illegal interface edit mode operation. */
72     return 0;
73   }
74   if (!(flags & 0x1) && GModuleDef_isDataProtected(es->env)) {
75     message(0,msgLookup("err.protdata"),es->env->m_name);			/* Not a library module */
76     return 0;
77   }
78   return 1;
79 }
80 
81 /*****************************************************************************
82  *****************************************************************************/
gat_hdl(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])83 static int gat_hdl(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
84 {
85   TkgGateWin *gw = TkGate.gw;
86   EditState *es = gw->parms->circuit->es;
87   int i;
88   const char *name = ((argc > 2) && (*argv[2] != '-')) ? argv[2] : 0;
89 
90 #if 0
91   {
92     printf("gat_hdl");
93     for (i = 1;i < argc;i++)
94       printf(" %s",argv[i]);
95     printf("\n");
96   }
97 #endif
98 
99   if (argc < 2) return TCL_ERROR;
100 
101   for (i = 1;i < argc;i++) {
102     if (strcmp(argv[i],"-cursor") == 0) {
103       int line,pos;
104       if (sscanf(argv[i+1],"%d.%d",&line,&pos) == 2) {
105 	hdl_saveCursor(name,line,pos);
106 	break;
107       }
108     }
109   }
110 
111   if (strcmp(argv[1],"load") == 0)
112     hdl_load(es->env);
113   else if (strcmp(argv[1],"save") == 0) {
114     if (hdl_save(name) < 0)
115       Tcl_SetResult(tcl, "cancel", TCL_STATIC);
116   } else if (strcmp(argv[1],"checksave") == 0) {
117       Tcl_SetResult(tcl, "cancel", TCL_STATIC);
118   } else if (strcmp(argv[1],"close") == 0) {
119     hdl_close();
120   } else if (strcmp(argv[1],"getindex") == 0) {
121     int line,pos;
122     if (hdl_getCursor(&line,&pos) == 0) {
123       char res[127];
124       sprintf(res,"%d.%d",line,pos);
125       Tcl_SetResult(tcl, res, TCL_VOLATILE);
126     } else
127       Tcl_SetResult(tcl, "1.0", TCL_STATIC);
128   } else if (strcmp(argv[1],"touch") == 0) {
129     ob_touch(TkGate.circuit);			/* Modify somthing to force undo to thing there are changes */
130   }
131 
132   return TCL_OK;
133 }
134 
135 /*
136  * Called to do final tkgate initilization
137  */
gat_init(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])138 static int gat_init(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
139 {
140   TkGate_init(tcl);
141   ClearModified();
142   ob_set_mode(OM_START);
143 
144   return TCL_OK;
145 }
146 
gat_reinitDelay(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])147 static int gat_reinitDelay(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
148 {
149   TkGate_initDelay();
150   return TCL_OK;
151 }
152 
153 /*
154  * Retrieve or store interface information about a module.
155  *
156  * gat_interface load <name> <array>
157  * gat_interface generate <name> <options>
158  * gat_interface puticon <name> <options>
159  * gat_interface geticon <name> <options>
160  *
161  */
gat_interface(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])162 static int gat_interface(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
163 {
164   if (argc < 3) {
165     Tcl_SetResult(tcl, "too few arguments.", TCL_STATIC);
166     return TCL_ERROR;
167   }
168 
169   if (igen_command(argv[1],argv[2],argc-3,argv + 3) != 0) {
170     Tcl_SetResult(tcl, "invalid command.", TCL_STATIC);
171     return TCL_ERROR;
172   }
173 
174   return TCL_OK;
175 }
176 
177 /*
178    gat_new "name.v" topmod
179 */
gat_new(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])180 static int gat_new(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
181 {
182   TkgGateWin *gw = TkGate.gw;
183   EditState **es = &gw->parms->circuit->es;
184   const char *file,*topMod;
185   GModuleDef *M;
186   ob_OMMode_t old_mode;
187 
188   assert(argc == 3);
189 
190   tkgate_setMajorMode(MM_EDIT);
191 
192   old_mode = ob_get_mode();
193   if (old_mode != OM_DISABLED) {
194     ob_set_mode(OM_DISABLED);
195   }
196   ob_clear();
197 
198   file = argv[1];
199   topMod = argv[2];
200   ob_touch(TkGate.circuit);
201   Circuit_initOptions(TkGate.circuit);
202   Circuit_setTitle(file);
203   ClearModified();
204 
205   Circuit_clear();
206   Circuit_setCurrentFile(file);
207 
208   Circuit_unloadAllLibraries(TkGate.circuit);
209 
210   editstate_flushModules(es);
211 
212   M = env_findAdd(topMod,1);
213   ob_touch(M);
214   TkGate.circuit->root_mod = M;
215 
216   editstate_push(es,M,0);
217   editstate_setCurrent(*es);
218   ob_touch(TkGate.circuit);
219 
220   ClearModified();
221 
222   DoTcl("LibraryMgr::loadBaseLibraries");
223 
224   /*
225    * Mark this so we can warn if we try to overwrite existing file.
226    */
227   TkGate.circuit->c_isNewFile = 1;
228 
229   FlagRedraw();
230 
231   if (old_mode == OM_ENABLED) {
232     ob_set_mode(old_mode);
233   }
234   return TCL_OK;
235 }
236 
237 /*
238    gat_load "name.v"
239 */
gat_load(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])240 static int gat_load(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
241 {
242   TkgGateWin *gw = TkGate.gw;
243   const char *name;
244   const char *modFlag;
245   ob_OMMode_t old_mode;
246 
247   assert(argc == 2);
248   name = argv[1];
249 
250   tkgate_setMajorMode(MM_EDIT);
251 
252   if ((modFlag = Tcl_GetVar(tcl,"tkg_modifiedFlag",TCL_GLOBAL_ONLY)) && *modFlag != '0') {
253     DoTcl("File::confDelMods");
254     if (!Tcl_GetStringResult(TkGate.tcl) || strcmp(Tcl_GetStringResult(TkGate.tcl),"yes") != 0) {
255       Tcl_SetResult(tcl,"0", TCL_STATIC);
256       return TCL_OK;
257     }
258   }
259 
260   old_mode = ob_get_mode();
261   if (old_mode != OM_DISABLED) {
262     ob_set_mode(OM_DISABLED);
263   }
264   ob_clear();
265 
266   ob_touch(gw->parms->circuit);
267   if (VerilogOpen(&gw->parms->circuit->es,name,0) < 0) {
268 
269     /*
270      * We failed to open the file, but if there is no current file we assume
271      * this was given on the command line and we are starting a new circuit.
272      */
273     if (!*CurrentFile_path(TkGate.circuit->currentFile)) {
274       /*  Circuit_setCurrentFile(name);*/
275     } else
276       message(1,msgLookup("err.badopen"),name);	/* Unable to open input file '%s' */
277 
278     ClearModified();
279 
280     if (old_mode == OM_ENABLED) {
281       ob_set_mode(old_mode);
282     }
283 
284     Tcl_SetResult(tcl,"0", TCL_STATIC);
285     return TCL_OK;
286   }
287 
288   sel_clearDelta();
289 
290   Circuit_setCurrentFile(name);
291 
292   ClearModified();
293   FlagRedraw();
294 
295   if (old_mode == OM_ENABLED) {
296     ob_set_mode(old_mode);
297   }
298 
299   Tcl_SetResult(tcl,"1", TCL_STATIC);
300   return TCL_OK;
301 }
302 
303 /*
304    gat_loadMore "name.v"
305 */
gat_loadMore(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])306 static int gat_loadMore(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
307 {
308   TkgGateWin *gw = TkGate.gw;
309   const char *name;
310 
311   assert(argc == 2);
312   name = argv[1];
313 
314   tkgate_setMajorMode(MM_EDIT);
315 
316   ob_touch(gw->parms->circuit);
317 
318   if (VerilogOpen(&gw->parms->circuit->es,name,1) < 0) {
319     Tcl_SetResult(tcl, "0", TCL_STATIC);
320     return TCL_OK;
321   }
322 
323   sel_clearDelta();
324 
325   Circuit_setCurrentFile(name);
326 
327   FlagRedraw();
328 
329   Tcl_SetResult(tcl, "1", TCL_STATIC);
330   return TCL_OK;
331 }
332 
333 
gat_libIsLoaded(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])334 static int gat_libIsLoaded(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
335 {
336   if (argc < 2)
337     return TCL_OK;
338 
339   if (SHash_find(TkGate.libraries,argv[1]))
340     Tcl_SetResult(TkGate.tcl, "1", TCL_STATIC);
341   else
342     Tcl_SetResult(TkGate.tcl, "0", TCL_STATIC);
343 
344   return TCL_OK;
345 }
346 
347 /*
348    gat_loadLibrary "name.v"
349 */
gat_loadLibrary(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])350 static int gat_loadLibrary(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
351 {
352   const char *name;
353 
354   assert(argc == 2);
355   name = argv[1];
356 
357   Circuit_loadLibrary(TkGate.circuit,name);
358 
359   return TCL_OK;
360 }
361 
362 /*****************************************************************************
363  *
364  * gat_unloadLibrary <name>
365  *
366  * Unload the named library.
367  *
368  *****************************************************************************/
gat_unloadLibrary(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])369 static int gat_unloadLibrary(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
370 {
371   const char *name;
372 
373   assert(argc == 2);
374   name = argv[1];
375 
376   Circuit_unloadLibrary(TkGate.circuit,name);
377 
378   FlagRedraw();
379 
380   return TCL_OK;
381 }
382 
gat_mode(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])383 static int gat_mode(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
384 {
385   TkgGateWin *gw = TkGate.gw;
386   int mode = 0;
387 
388   assert(argc == 2);
389 
390   sscanf(argv[1],"%d",&mode);
391 
392   setEditMode(gw->parms->circuit->es,mode);
393 
394   return TCL_OK;
395 }
396 
397 
398 /*
399    gat_make and {opts}
400 */
gat_make(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])401 static int gat_make(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
402 {
403   TkgGateWin *gw = TkGate.gw;
404   EditState *es = gw->parms->circuit->es;
405   EditState **pes = &gw->parms->circuit->es;
406   GGateInfo *GI;
407   int x,y,r;
408   GCElement *g;
409   const char *xstr,*ystr;
410   const char *dodraw_s = "1";
411   int dodraw = 1;
412 
413   assert(argc >=  2);
414 
415   dodraw_s  = seekOption("-dodraw",argv+2,argc-2);
416   if (dodraw_s)
417     dodraw = (*dodraw_s != '0');
418 
419   /*
420    * If we are in interface mode and we are requesting to make a block, use this as
421    * an indication that we want to open that block for interface testing.
422    */
423   if (editstate_isInterfaceMode()) {
424     const char *func = seekOption("-func",argv+2,argc-2);
425 
426     if (func) {
427       modint_openSelected(func);
428     }
429 
430     return TCL_OK;
431   }
432 
433   if (tkgate_currentMode() != MM_EDIT) return TCL_OK;
434   if (!modifyOK(es,0)) return TCL_OK;
435 
436   xstr = seekOption("-x",argv+2,argc-2);
437   ystr = seekOption("-y",argv+2,argc-2);
438 
439   if (xstr && ystr) {
440     sscanf(xstr,"%d",&x);
441     sscanf(ystr,"%d",&y);
442     r = EditState_getRotation();
443     x /= TkGate.circuit->zoom_factor;
444     y /= TkGate.circuit->zoom_factor;
445     x = wtoc_x(x);
446     y = wtoc_y(y);
447   } else if (TkGate.ed->mark_vis) {
448     x = TkGate.ed->tx;
449     y = TkGate.ed->ty;
450     r = EditState_getRotation();
451   } else {
452     message(0,msgLookup("err.nomark"));	/* Please set a mark with the left mouse button before selecting a gate type. */
453     return TCL_OK;
454   }
455 
456   GI = GGateInfo_lookup(argv[1]);
457   if (!GI) {
458     message(1,msgLookup("err.badgate"),argv[1]);	/* Unknown gate type. */
459     return TCL_OK;
460   }
461 
462   badermessage(GI->name);
463 
464   mark_unpost();
465 
466   g = (*GI->MakeFunction)(pes,es->env,GI->code,x,y,r,0,0,argv+2,argc-2);
467 
468   if (!g) return TCL_OK;			/* Make was canceled */
469 
470   if (TkGate.defaultTech) {
471     ob_touch(g);
472     ob_free(g->tech);
473     g->tech = ob_strdup(TkGate.defaultTech);
474   }
475 
476   if (dodraw)
477     gate_draw(g,0);
478 
479   if ((GI->code == GC_BLOCK || GI->code == GC_SYMBLOCK))
480     SetModified(MF_MODULE);
481 
482   if (dodraw && g && pes) {
483     sel_appendGate(*pes,g,1);
484     sel_finish(*pes);
485     ob_touch(TkGate.circuit);
486     TkGate.circuit->select = g;
487 
488     if ((GI->code == GC_BLOCK || GI->code == GC_SYMBLOCK) && r != 0) {
489       gate_draw(g,0);
490       while (r-- > 0)
491 	sel_rotate(*pes,1);
492       gate_draw(g,0);
493     }
494   }
495 
496   scrollbar_bbx_update();
497 
498   SynchronizeInterface();
499 
500   return TCL_OK;
501 }
502 
gat_closeBox(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])503 static int gat_closeBox(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
504 {
505   TkgGateWin *gw = TkGate.gw;
506   EditState **es = &gw->parms->circuit->es;
507 
508   if (!(*es)->parent) {
509     message(0,msgLookup("err.closeroot"));	/* "Can't close top-level module.  Use quit." */
510     return TCL_OK;
511   }
512 
513   ob_touch(TkGate.circuit);
514   EditState_unselectGate(*es);
515   editstate_pop(es);
516   editstate_setCurrent(*es);
517   ClearErrorMark();
518   net_unselect(0);
519   cpath_reshow();
520 
521   SetModified(MF_MODULE);
522   SynchronizeInterface();
523 
524   FlagRedraw();
525 
526   return TCL_OK;
527 }
528 
529 /*****************************************************************************
530  *
531  * Open the specified or currently selected module in the module editor.
532  *
533  * Usage:
534  *    gat_openBox [<module-name>]
535  *    gat_openBox -hierarchical [<module-name>]
536  *
537  *****************************************************************************/
gat_openBox(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])538 static int gat_openBox(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
539 {
540   TkgGateWin *gw = TkGate.gw;
541   EditState **es = &gw->parms->circuit->es;
542   GModuleDef *M = 0;
543   GCElement *b = 0;
544   const char *modName = 0;
545   int hierarchical = 1;
546 
547   if (argc == 2) {
548     modName = argv[1];
549     hierarchical = 0;
550   } else if (argc == 3) {
551     modName = argv[2];
552     hierarchical = 1;
553   }
554 
555   if (hdl_checkSave(0) < 0) {		/* Make sure hdl is up to date */
556     Tcl_SetResult(tcl, "cancel", TCL_STATIC);
557     return TCL_OK;
558   }
559 
560   /*
561    * Opening already selected module.
562    */
563   if (modName && es && *es && (*es)->env && strcmp((*es)->env->m_name,modName) == 0)
564     return TCL_OK;
565 
566   ob_touch(TkGate.circuit);
567 
568   /*
569    * If we are in interface mode, just change the interface we are editing.
570    */
571   if ((*es)->isInterface) {
572     modint_openSelected(modName);
573     return TCL_OK;
574   }
575 
576   if (!hierarchical) {
577     /* NOTE: The 'jump-to-module' feature can not be used in simulation or analysis mode. */
578 
579     if (tkgate_currentMode() == MM_SIMULATE) {
580       SimInterface_navigateToModule(es,modName);
581       return TCL_OK;
582     }
583   }
584 
585   if (modName) {
586     char *p;
587 
588     /*
589      * Trim all but the last module name
590      */
591     p = strrchr(modName,'/');
592     if (p) modName = p+1;
593 
594     M = env_findModule(modName);
595     if (!M) {
596       message(1,msgLookup("err.nomod"),modName);		/* Module '%s' is not defined. */
597       return TCL_OK;
598     }
599   } else {
600     b = TkGate.circuit->select;
601     if (b && GCElement_isModule(b))
602       M = env_findAdd(b->u.block.moduleName,0);
603     else
604       return TCL_OK;
605   }
606 
607   if (M->m_hidden && tkgate_currentMode() == MM_EDIT) {
608     message(1,msgLookup("err.modlock"));			/* Logic Block is Locked! */
609     return TCL_OK;
610   }
611 
612   EditState_unselectGate(*es);
613 
614   if (hierarchical) {
615     if (b) block_explode(b);
616     editstate_push(es,M,b);
617   } else {
618     while (*es)
619       editstate_pop(es);
620     editstate_push(es,M,0);
621   }
622   editstate_setCurrent(*es);
623   ClearErrorMark();
624   net_unselect(0);
625   cpath_reshow();
626 
627   SetModified(MF_MODULE|MF_SYNCONLY);
628   SynchronizeInterface();
629 
630   FlagRedraw();
631 
632   return TCL_OK;
633 }
634 
635 /*****************************************************************************
636  *
637  * Set top-level module.
638  *
639  * Usage:
640  *    gat_reroot <module-name>
641  *
642  *****************************************************************************/
gat_reroot(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])643 static int gat_reroot(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
644 {
645   GModuleDef *M;
646 
647   assert(argc == 2);
648   M = env_findModule(argv[1]);
649   if (!M) {
650     message(1,msgLookup("err.nomod"),argv[1]);		/* Module '%s' is not defined. */
651     return TCL_OK;
652   }
653 
654   Circuit_changeRoot(M);
655 
656   SynchronizeInterface();
657   FlagRedraw();
658   return TCL_OK;
659 }
660 
661 /*****************************************************************************
662  * Get the list of available printers
663  *
664  * Usage:
665  *    gat_getPrinterList
666  *
667  * The returned list is of the form: {{name1 longname1} {name2 longname2} ...}
668  *
669  *****************************************************************************/
gat_getPrinterList(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])670 static int gat_getPrinterList(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
671 {
672   char *printerList = malloc(STRMAX);
673   int N = STRMAX;
674   int C = 0;
675   FILE *f;
676 
677   strcpy(printerList,"{default \"Default Printer\"}");
678   C = strlen(printerList);
679 
680   f = fopen("/etc/printcap","r");
681   if (f) {
682     char buf[STRMAX*2];
683 
684     while (readprintcapentry(buf,2*STRMAX,f)) {
685       char *nameEntry;
686       char *shortName = 0;
687       char *longName = 0;
688       char *t;
689       int l;
690 
691       nameEntry = strtok(buf,":");
692       for (t = strtok(nameEntry,"|");t && !(shortName && longName);t = strtok(0,"|")) {
693 	if (strchr(t,' ') && !longName)
694 	  longName = t;
695 	else if (!shortName)
696 	  shortName = t;
697       }
698       if (!shortName) continue;
699       if (!longName) longName = shortName;
700 
701       l = strlen(shortName) + strlen(longName) + 6;
702       if (C >= N) {
703 	N += STRMAX;
704 	printerList = realloc(printerList,N);
705       }
706 
707       sprintf(printerList + C," {%s \"%s\"}",shortName,longName);
708       C += l;
709     }
710     fclose(f);
711   }
712 
713   Tcl_SetResult(TkGate.tcl, printerList, TCL_VOLATILE);
714 
715   free(printerList);
716 
717   return TCL_OK;
718 }
719 
720 /*****************************************************************************
721  *
722  * setrot {0/90/180/270}
723  *
724  * set rotation for new gates
725  *
726  *****************************************************************************/
gat_setrot(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])727 static int gat_setrot(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
728 {
729   char buf[STRMAX];
730   int N = 0;
731 
732   assert(argc == 2);
733 
734   sscanf(argv[1],"%d",&N);
735   EditState_setRotation(N);
736 
737   sprintf(buf,"%d",N);
738   Tcl_SetVar(TkGate.tcl,"rot",buf,TCL_GLOBAL_ONLY);
739 
740 
741   return TCL_OK;
742 }
743 
744 /*
745    Relay a command from the simulator to the scope
746 */
gat_scopeCommand(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])747 static int gat_scopeCommand(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
748 {
749   SimInterface_command(&TkGate.circuit->simulator,argv[1]);
750   return TCL_OK;
751 }
752 
753 /*
754    Relay a command from the analyzer to cpath
755 */
gat_analyzerCommand(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])756 static int gat_analyzerCommand(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
757 {
758   cpath_command(argv[1]);
759   return TCL_OK;
760 }
761 
gat_errBoxReport(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])762 static int gat_errBoxReport(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
763 {
764   TkgGateWin *gw = TkGate.gw;
765   EditState **es = &gw->parms->circuit->es;
766   int N = 0;
767 
768   ob_touch(TkGate.circuit);
769 
770   char res[127];
771   if (argc != 2 || sscanf(argv[1],"%d",&N) != 1) {
772     if (argc != 2)
773       sprintf(res,"argument error argc=%d",argc);
774     else
775       sprintf(res,"argument error argv[1]=<%s>",argv[1]);
776     Tcl_SetResult(tcl, res, TCL_VOLATILE);
777     return TCL_ERROR;
778   }
779 
780   if (N >=0 && tkgate_currentMode() == MM_SIMULATE) {
781     DoTcl("errmsg [m db.err.neededit]");
782     return TCL_OK;
783   }
784 
785   if (N >= 0)
786     *es = EditState_moveToError(N,*es);
787   else {
788     Error_purge();
789   }
790 
791   return TCL_OK;
792 }
793 
794 /*****************************************************************************
795  *
796  * Save the current circuit to a file.
797  *
798  * Tcl syntax:
799  *
800  * gat_save <filename>
801  *
802  *****************************************************************************/
gat_saveCircuit(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])803 static int gat_saveCircuit(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
804 {
805   const char *fileName = argv[1];
806 
807   assert(argc == 2);
808 
809   if (TkGate.circuit->c_isNewFile) {
810     FILE *f = fopen(fileName,"r");
811     int abortSave = 0;
812 
813     if (f) {
814       DoTcl("yesno [format [m circ.reallyoverwrite] %s]",fileName);
815       if (strcmp(Tcl_GetStringResult(tcl),"yes") != 0)
816 	abortSave = 1;
817 
818       fclose(f);
819     }
820     if (abortSave) return TCL_OK;
821   }
822 
823 
824   ob_begin_framef("-Save",FF_TRANSPARENT);
825   ob_touch(TkGate.circuit);
826   TkGate.circuit->c_isNewFile = 0;
827   VerilogSave(fileName);
828   Circuit_setCurrentFile(fileName);
829   ob_end_frame();
830 
831   return TCL_OK;
832 }
833 
834 
gat_addPort(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])835 static int gat_addPort(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
836 {
837   TkgGateWin *gw = TkGate.gw;
838   EditState *es = gw->parms->circuit->es;
839   GCElement *g;
840   GGateInfo *gi;
841   int i;
842 
843   if (!modifyOK(es,2)) return TCL_OK;
844 
845   g = TkGate.circuit->select;
846   if (!g) return TCL_OK;
847   gi = g->typeinfo;
848 
849   if (gi->code == GC_BLOCK) {
850     message(1,msgLookup("err.oldportact"));
851     return TCL_OK;
852   }
853 
854 
855   /* Find port that can be extended. */
856   for (i = 0;i < gi->NumPads;i++)
857     if (gi->Pad[i].CanAdd) break;
858 
859   if (i >= gi->NumPads) {
860     message(1,msgLookup("err.badportadd"));
861     return TCL_OK;
862   }
863 
864   if (gi->Pad[i].iotype == IN )
865     (*gi->AddInput)(es,TkGate.circuit->select);
866   else if (gi->Pad[i].iotype == OUT)
867     (*gi->AddOutput)(es,TkGate.circuit->select);
868   else
869     (*gi->AddTri)(es,TkGate.circuit->select);
870 
871   sel_refinish(es);
872 
873   return TCL_OK;
874 }
875 
gat_changePinDir(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])876 static int gat_changePinDir(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
877 {
878   TkgGateWin *gw = TkGate.gw;
879   EditState *es = gw->parms->circuit->es;
880 
881   if (!TkGate.circuit->select)
882     return TCL_OK;
883 
884   (*TkGate.circuit->select->typeinfo->ChangePin)(es,TkGate.circuit->select);
885 
886   sel_refinish(es);
887 
888   return TCL_OK;
889 }
890 
gat_dohyperlink(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])891 static int gat_dohyperlink(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
892 {
893   if (argc == 2) {
894     dohyperlink(argv[1]);
895   }
896   return TCL_OK;
897 }
898 
899 /*
900     Delete selected gate.
901 */
gat_deleteSelected(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])902 static int gat_deleteSelected(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
903 {
904   TkgGateWin *gw = TkGate.gw;
905   EditState *es = gw->parms->circuit->es;
906 
907   if (!es) return TCL_OK;
908 
909   if (!modifyOK(es,2)) return TCL_OK;
910 
911   if ((es)->isInterface) {
912     sel_interfaceReset(es);
913     return TCL_OK;
914   }
915 
916   if (TkGate.circuit->select || TkGate.circuit->mg_selection) {
917     sel_delete(es);
918     scrollbar_bbx_update();
919   } else if (DoTcl("tkg_getSelectedBlock") == TCL_OK && Tcl_GetStringResult(tcl)[0] != 0) {
920     DoTcl("BlockOp::delete");
921   } else {
922     message(1,msgLookup("err.nodel"));		/* "No deletable selection." */
923     return TCL_OK;
924   }
925 
926   SynchronizeInterface();
927 
928   return TCL_OK;
929 }
930 
gat_replicate(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])931 static int gat_replicate(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
932 {
933   TkgGateWin *gw = TkGate.gw;
934   EditState *es = gw->parms->circuit->es;
935 
936   if (!modifyOK(es,0)) return TCL_OK;
937 
938   setEditMode(es,MODE_REPLICATE);
939   scrollbar_bbx_update();
940 
941   return TCL_OK;
942 }
943 
gat_renameBlock(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])944 static int gat_renameBlock(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
945 {
946   TkgGateWin *gw = TkGate.gw;
947   EditState **es = &gw->parms->circuit->es;
948   const char *oldName,*newName;
949   const char *curName = TkGate.circuit->es->env->m_name;
950   int isCurrentRename = 0;
951 
952   assert(argc == 3);
953   oldName = argv[1];
954   newName = argv[2];
955 
956 
957   /*
958    * Test to see if we are renaming the module we have open.
959    */
960   if (strcmp(oldName,curName) == 0) {
961     isCurrentRename = 1;
962   }
963 
964   if (checkValidName(argv[2],0) != 0) {
965     message(1,msgLookup("err.badid"),argv[2]);
966     return TCL_OK;
967   }
968 
969   if (!env_findModule(oldName)) {
970     message(1,msgLookup("err.modnotdef"),oldName);	/* "Module '%s' is undefined." */
971     return TCL_OK;
972   }
973 
974   if (env_findModule(newName)) {
975     message(1,msgLookup("err.moddef"),newName);		/* "The block '%s' already exists." */
976     return TCL_OK;
977   }
978 
979   env_rename(oldName,newName);
980 
981 
982   SetModified(MF_NET|MF_GATE|MF_MODULE);
983 
984   if (isCurrentRename) {
985     editstate_setCurrent(*es);
986     SynchronizeInterface();
987     FlagRedraw();
988   }
989 
990   return TCL_OK;
991 }
992 
gat_computestrhash(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])993 static int gat_computestrhash(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
994 {
995   if (argc != 2) {
996     Tcl_SetResult(tcl, "wrong number of parameters.", TCL_STATIC);
997     return TCL_ERROR;
998   }
999 
1000   Tcl_SetObjResult(tcl, Tcl_NewLongObj(computestrhash(argv[1])));
1001 
1002   return TCL_OK;
1003 }
1004 
gat_copyBlock(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1005 static int gat_copyBlock(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1006 {
1007   TkgGateWin *gw = TkGate.gw;
1008   EditState *es = gw->parms->circuit->es;
1009 
1010   if (checkValidName(argv[2],0) != 0) {
1011     message(1,msgLookup("err.badid"),argv[2]);
1012     return TCL_OK;
1013   }
1014 
1015   env_copy(es,argv[1],argv[2]);
1016 
1017   SetModified(MF_MODULE);
1018 
1019   return TCL_OK;
1020 }
1021 
1022 /*****************************************************************************
1023  *
1024  * This function has no specific purpose.  It is simply a placehold to put
1025  * debugging code for whatever bug I am currently trying to fix
1026  *
1027  *****************************************************************************/
gat_debug(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1028 static int gat_debug(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1029 {
1030   GModuleDef *m = env_findModule("REGS");
1031   GCElement *g;
1032   int n;
1033   int i;
1034 
1035   if (GCElement_getType(m->m_interface) == GC_SYMBLOCK)
1036     g = m->m_interface;
1037   else
1038     g = m->m_altInterface;
1039 
1040 
1041   n = GCElement_numPads(g);
1042 
1043   printf("REGS-symbol %p\n",g);
1044   for (i = 0;i < n;i++) {
1045     const char *name = GCElement_getPadName(g,i);
1046     /**
1047      * @TODO to remove
1048      */
1049     /* GWire *w = g->wires[i]; */
1050     printf("   pad %s:\n",name);
1051   }
1052 
1053   return TCL_OK;
1054 }
1055 
1056 /*****************************************************************************
1057  *
1058  * gat_deletBlock <name>
1059  *
1060  * Delete the named module
1061  *
1062  *****************************************************************************/
gat_deleteBlock(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1063 static int gat_deleteBlock(ClientData _d,Tcl_Interp *tcl,
1064 			   int argc,const char *argv[])
1065 {
1066   TkgGateWin *gw = TkGate.gw;
1067   EditState *es = gw->parms->circuit->es;
1068 
1069   if (argv[1])
1070     env_delete(es,argv[1]);
1071 
1072   return TCL_OK;
1073 }
1074 
gat_claimBlock(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1075 static int gat_claimBlock(ClientData _d,Tcl_Interp *tcl,
1076 			  int argc,const char *argv[])
1077 {
1078   GModuleDef *M;
1079 
1080   if (argc < 2) return TCL_OK;
1081 
1082   M = env_findModule(argv[1]);
1083   if (M) {
1084     if (!M->m_isLib) {
1085       message(1,msgLookup("msg.notlib"),argv[1]);	/* Not a library module */
1086       return TCL_OK;
1087     }
1088 
1089     /*    DoTcl("tkg_blockListSetLibFlag %s 0",argv[1]);*/
1090     GModuleDef_claim(M);
1091     SetModified(MF_MODULE);
1092   }
1093 
1094   return TCL_OK;
1095 }
1096 
1097 /*****************************************************************************
1098  * gat_newBlock name
1099  *
1100  *****************************************************************************/
gat_newBlock(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1101 static int gat_newBlock(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1102 {
1103   GModuleDef *M;
1104   char *aname;
1105   const char *modName;
1106 
1107   if (argc != 2) {
1108     Tcl_SetResult(tcl, "wrong number of arguments.", TCL_STATIC);
1109     return TCL_ERROR;
1110   }
1111 
1112   aname = (char*)argv[1];
1113 
1114   Tcl_SetVar2(tcl,aname,"ok","0",TCL_GLOBAL_ONLY);
1115 
1116   modName = Tcl_GetVar2(tcl,aname,"name",TCL_GLOBAL_ONLY);
1117   if (!modName || !*modName || checkValidName(modName,0) != 0) {
1118     message(1,msgLookup("err.badid"),modName);
1119     return TCL_OK;
1120   }
1121   if (env_findModule(modName)) {
1122     message(1,msgLookup("err.moddef"),modName);
1123     return TCL_OK;
1124   }
1125   if (strncmp(modName,TkGate.circuit->c_gatePrefix,strlen(TkGate.circuit->c_gatePrefix)) == 0) {
1126     message(1,msgLookup("err.primprefix"),modName,TkGate.circuit->c_gatePrefix);
1127     return TCL_OK;
1128   }
1129   if (ycIsKW((char*)modName)) {
1130     message(1,msgLookup("err.iskeyword"),modName);
1131     return TCL_OK;
1132   }
1133 
1134   M = env_defineModule(modName,0);
1135   if (M) {
1136     const char *r;
1137 
1138     r = Tcl_GetVar2(tcl,aname,"ppos",TCL_GLOBAL_ONLY);
1139     M->m_pptype = (strcmp(r,"fix") == 0) ? PPT_FIXED : PPT_SCALED;
1140 
1141     r = Tcl_GetVar2(tcl,aname,"type",TCL_GLOBAL_ONLY);
1142     M->m_type = (strcmp(r,"netlist") == 0) ? MT_NETLIST : MT_TEXTHDL;
1143 
1144     r = Tcl_GetVar2(tcl,aname,"prot",TCL_GLOBAL_ONLY);
1145     M->m_protData = strbin(r);
1146 
1147     r = Tcl_GetVar2(tcl,aname,"protint",TCL_GLOBAL_ONLY);
1148     M->m_protIntf = strbin(r);
1149 
1150     r = Tcl_GetVar2(tcl,aname,"proted",TCL_GLOBAL_ONLY);
1151     M->m_protEdit = strbin(r);
1152 
1153     Tcl_SetVar2(tcl,aname,"ok","1",TCL_GLOBAL_ONLY);
1154   }
1155 
1156   if (M->m_type == MT_TEXTHDL) {
1157     char buf[STRMAX];
1158 
1159     sprintf(buf,"module %s;\n\nendmodule\n",M->m_name);
1160     GModuleDef_saveText(M,buf);
1161   }
1162 
1163   return TCL_OK;
1164 }
1165 
gat_batInc(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1166 static int gat_batInc(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1167 {
1168   TkgGateWin *gw = TkGate.gw;
1169   EditState *es = gw->parms->circuit->es;
1170 
1171   if (TkGate.batp) {
1172     SetBatCursor(es);
1173     Tcl_Eval(tcl,"after $tkg_batRate gat_batInc");
1174   }
1175 
1176   return TCL_OK;
1177 }
1178 
1179 /*****************************************************************************
1180  *
1181  *  Set variables for the delays of the currently seleced gate in the specified tecnology
1182  *
1183  ******************************************************************************/
gat_setGateTechDelays(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1184 static int gat_setGateTechDelays(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1185 {
1186   GCElement *g = TkGate.circuit->select;
1187   GDelayDef *dd;
1188   GGateInfo *gi;
1189   int i;
1190   int delays[MAXDELAYS];
1191 
1192   if (!g) return TCL_OK;
1193   gi = g->typeinfo;
1194 
1195   dd = GDelayDef_findTech(gi->delay_defs,argv[1]);
1196   if (!dd) return TCL_OK;
1197 
1198   if (GDelayDef_getDelays(dd, g, delays) < 0)
1199     return TCL_OK;
1200 
1201   for (i = 0;i < gi->num_delays;i++) {
1202     DoTcl("set ::edgat_techdelay(%s) %d",gi->delayNames[i],delays[i]);
1203   }
1204   DoTcl("update");
1205   return TCL_OK;
1206 }
1207 
1208 /*
1209  * gat_editProps
1210  *
1211  * Used for implementing the edit gate (or net) properties boxes.  This
1212  * should probably be rewritten at some time to use the same dialog box
1213  * model as module properties boxes.
1214  *
1215  */
gat_editProps(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1216 static int gat_editProps(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1217 {
1218   TkgGateWin *gw = TkGate.gw;
1219   EditState **es = &gw->parms->circuit->es;
1220   GCElement *g = TkGate.circuit->select;
1221   GGateInfo *gi;
1222   const char *temp;
1223   int ok;
1224 
1225   /*
1226    * If we are editing the interface, then switch to editing a specific module.
1227    */
1228   if ((*es)->isInterface) {
1229     if (g->typeinfo->code == GC_BLOCK) {
1230       GWire *w = block_hitPort(g,TkGate.ed->tx,TkGate.ed->ty);
1231       if (w) {
1232 	block_setPortName(g,w,*es);
1233 	return TCL_OK;
1234       }
1235     }
1236 
1237     if (editstate_getInterfaceMode() == INTFMODE_ALL)
1238       modint_openSelected(0);
1239     return TCL_OK;
1240   }
1241 
1242   if ((!g || g->typeinfo->code == GC_JOINT) && TkGate.circuit->nsel) {
1243     DoTcl("gat_editNet %s",TkGate.circuit->nsel->n_signame);
1244     return TCL_OK;
1245   }
1246 
1247   if (!g) {
1248     DoTcl("SideBar::editModuleOrNet");
1249     return TCL_OK;
1250   }
1251   gi = g->typeinfo;
1252 
1253   switch (gi->code) {
1254   case GC_BLOCK :
1255     {
1256       GWire *w = block_hitPort(g,TkGate.ed->tx,TkGate.ed->ty);
1257       if (w) {
1258 	block_setPortName(g,w,*es);
1259 	return TCL_OK;
1260       }
1261     }
1262     break;
1263   case GC_JOINT :
1264     return TCL_OK;
1265   case GC_LOGICIN :
1266   case GC_LOGICTRI :
1267   case GC_LOGICOUT :
1268     net_editProps(g->wires[0]->net,TkGate.ed->tx,TkGate.ed->ty);
1269     return TCL_OK;
1270   }
1271 
1272   if (!gi->EditProps) {
1273     message(1,msgLookup("err.noprop"));	/* Selected gate has no editable properites. */
1274     return TCL_OK;
1275   }
1276 
1277 
1278   /*
1279    * Standard gate properties editing.
1280    */
1281 #if 0
1282   printf("gat_editProps g=%p gi=%p [%s]\n",g,gi,gi->name);
1283 #endif
1284   (*gi->EditProps)(g,1);
1285   DoTcl("EditGate::post");
1286   if ((temp = Tcl_GetVar(tcl,"edgat_ok",TCL_GLOBAL_ONLY)) && sscanf(temp,"%d",&ok) == 1 && ok) {
1287     if (GModuleDef_isDataProtected(TkGate.circuit->es->env)) {
1288       message(0,msgLookup("err.protdata"));		/* "Can not edit library module." */
1289       return TCL_OK;
1290     }
1291 
1292     if (tkgate_currentMode() == MM_EDIT)
1293       (*gi->EditProps)(g,0);
1294     else
1295       message(1,msgLookup("err.noteditpchg"));
1296   }
1297 
1298   sel_refinish(*es);
1299 
1300   return TCL_OK;
1301 }
1302 
1303 /*****************************************************************************
1304  * gat_editCircProps <command> <array>
1305  *
1306  * Save or load properties about the circuit. "<command>" is either "load" or "save"
1307  *
1308  *
1309  *   file		File name
1310  *   filev		File version
1311  *   title		Circuit title
1312  *   discard		Discard changes on quiting (used for tutorial circuits)
1313  *   extbar		Extender bar style
1314  *   scripts		List of simulator scripts
1315  *
1316  *****************************************************************************/
gat_editCircProps(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1317 static int gat_editCircProps(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1318 {
1319   static char *tvModeNames[] = {"never","after","all"};
1320   char *aname = 0;
1321   Circuit *c = TkGate.circuit;
1322 
1323   if (argc != 3) {
1324     Tcl_SetResult(tcl, "wrong number of arguments.", TCL_STATIC);
1325     return TCL_ERROR;
1326   }
1327 
1328   /* Tcl/Tk 8.3 wants non-const parameters to SetVar */
1329   aname = (char*)argv[2];
1330 
1331   if (strcmp(argv[1],"load") == 0) {
1332     int n;
1333     char u[STRMAX];
1334 
1335     Tcl_SetVar2(tcl,aname,"file",CurrentFile_path(c->currentFile),TCL_GLOBAL_ONLY);
1336     Tcl_SetVar2(tcl,aname,"filev",c->fileVersion,TCL_GLOBAL_ONLY);
1337     Tcl_SetVar2(tcl,aname,"title",c->title,TCL_GLOBAL_ONLY);
1338     Tcl_SetVar2(tcl,aname,"encoding",c->c_encoding,TCL_GLOBAL_ONLY);
1339     Tcl_SetVar2(tcl,aname,"locale",c->c_locale->l_name,TCL_GLOBAL_ONLY);
1340     Tcl_SetVar2(tcl,aname,"discard",binstr(c->discardChanges),TCL_GLOBAL_ONLY);
1341     Tcl_SetVar2(tcl,aname,"extbar",binstr(c->useExtBars),TCL_GLOBAL_ONLY);
1342     Tcl_SetVar2(tcl,aname,"shownet",binstr(c->showSwitchNets),TCL_GLOBAL_ONLY);
1343     Tcl_SetVar2(tcl,aname,"autostart",binstr(c->simAutoStart),TCL_GLOBAL_ONLY);
1344     Tcl_SetVar2(tcl,aname,"clockMode",binstr(c->simClockMode),TCL_GLOBAL_ONLY);
1345     Tcl_SetVar2(tcl,aname,"clockName",c->simClockName,TCL_GLOBAL_ONLY);
1346     if (c->numInitScripts > 0) {
1347       char *scripts = Tcl_Merge(c->numInitScripts,(const char**)c->initScripts);
1348       Tcl_SetVar2(tcl,aname,"scripts",scripts,TCL_GLOBAL_ONLY);
1349       if (scripts)
1350 	Tcl_Free((char*)scripts);
1351     } else
1352       Tcl_SetVar2(tcl,aname,"scripts","",TCL_GLOBAL_ONLY);
1353 
1354     Timescale_decode(c->c_timescale.ts_units, &n, u);
1355     Tcl_SetVar2(tcl,aname,"unitsU",u,TCL_GLOBAL_ONLY);
1356     sprintf(u,"%d",n);
1357     Tcl_SetVar2(tcl,aname,"unitsN",u,TCL_GLOBAL_ONLY);
1358 
1359     Timescale_decode(c->c_timescale.ts_precision, &n, u);
1360     Tcl_SetVar2(tcl,aname,"precisionU",u,TCL_GLOBAL_ONLY);
1361     sprintf(u,"%d",n);
1362     Tcl_SetVar2(tcl,aname,"precisionN",u,TCL_GLOBAL_ONLY);
1363 
1364     sprintf(u,"%lg",c->c_startup);
1365     Tcl_SetVar2(tcl,aname,"initMode",tvModeNames[c->c_tvMode],TCL_GLOBAL_ONLY);
1366     Tcl_SetVar2(tcl,aname,"initTime",u,TCL_GLOBAL_ONLY);
1367     Tcl_SetVar2(tcl,aname,"initUnits",Timescale_codeToUnits(c->c_startupUnits),TCL_GLOBAL_ONLY);
1368   } else if (strcmp(argv[1],"save") == 0) {
1369     const char *r;
1370     int numScripts;
1371     const char **scriptList;
1372     int n;
1373     Locale *locale;
1374 
1375     r = Tcl_GetVar2(tcl,aname,"ok",TCL_GLOBAL_ONLY);
1376     if (r && *r == '1') {
1377       r = Tcl_GetVar2(tcl,aname,"discard",TCL_GLOBAL_ONLY);
1378       c->discardChanges = strbin(r);
1379       r = Tcl_GetVar2(tcl,aname,"extbar",TCL_GLOBAL_ONLY);
1380       c->useExtBars = strbin(r);
1381       r = Tcl_GetVar2(tcl,aname,"shownet",TCL_GLOBAL_ONLY);
1382       c->showSwitchNets = strbin(r);
1383       r = Tcl_GetVar2(tcl,aname,"autostart",TCL_GLOBAL_ONLY);
1384       c->simAutoStart = strbin(r);
1385       r = Tcl_GetVar2(tcl,aname,"title",TCL_GLOBAL_ONLY);
1386       Circuit_setTitle(r);
1387       r = Tcl_GetVar2(tcl,aname,"encoding",TCL_GLOBAL_ONLY);
1388       Circuit_setFileEncoding(c,r);
1389 
1390       r = Tcl_GetVar2(tcl,aname,"locale",TCL_GLOBAL_ONLY);
1391       locale = (Locale*)SHash_find(TkGate.localeNameTable,r);
1392       if (locale && c->c_locale != locale) {
1393 	Circuit_setLocale(c,locale);
1394 	FlagRedraw();
1395       }
1396 
1397       r = Tcl_GetVar2(tcl,aname,"clockMode",TCL_GLOBAL_ONLY);
1398       c->simClockMode = strbin(r);
1399       r = Tcl_GetVar2(tcl,aname,"clockName",TCL_GLOBAL_ONLY);
1400       Circuit_setClockName(r);
1401 
1402       r = Tcl_GetVar2(tcl,aname,"scripts",TCL_GLOBAL_ONLY);
1403       if (Tcl_SplitList(tcl,r,&numScripts,&scriptList) == TCL_OK) {
1404 	Circuit_setScripts(numScripts,scriptList);
1405 	if (scriptList)
1406 	  Tcl_Free((char*)scriptList);
1407       }
1408 
1409       r = Tcl_GetVar2(tcl,aname,"unitsN",TCL_GLOBAL_ONLY);
1410       sscanf(r,"%d",&n);
1411       r = Tcl_GetVar2(tcl,aname,"unitsU",TCL_GLOBAL_ONLY);
1412       c->c_timescale.ts_units = Timescale_parse(n,r);
1413       r = Tcl_GetVar2(tcl,aname,"precisionN",TCL_GLOBAL_ONLY);
1414       sscanf(r,"%d",&n);
1415       r = Tcl_GetVar2(tcl,aname,"precisionU",TCL_GLOBAL_ONLY);
1416       c->c_timescale.ts_precision = Timescale_parse(n,r);
1417 
1418       if (c->c_timescale.ts_precision > c->c_timescale.ts_units)
1419 	c->c_timescale.ts_precision = c->c_timescale.ts_units;
1420 
1421       r = Tcl_GetVar2(tcl,aname,"initMode",TCL_GLOBAL_ONLY);
1422       for (n = 0;n < 3;n++)
1423 	if (strcmp(r,tvModeNames[n]) == 0) {
1424 	  c->c_tvMode = n;
1425 	  break;
1426 	}
1427       r = Tcl_GetVar2(tcl,aname,"initTime",TCL_GLOBAL_ONLY);
1428       sscanf(r,"%lf",&c->c_startup);
1429       r = Tcl_GetVar2(tcl,aname,"initUnits",TCL_GLOBAL_ONLY);
1430       c->c_startupUnits = Timescale_unitsToCode(r);
1431       if (c->c_startupUnits < 0) {
1432 	c->c_startupUnits = UC_NANOSEC;
1433 	logError(ERL_WARN,"bad unit code in gat_editCircProps.");
1434       }
1435     }
1436   } else {
1437     Tcl_SetResult(tcl, "bad command.", TCL_STATIC);
1438     return TCL_ERROR;
1439   }
1440 
1441  Tcl_SetVar2(tcl,aname,"ok","1",TCL_GLOBAL_ONLY);
1442 
1443   return TCL_OK;
1444 }
1445 
1446 
1447 /*****************************************************************************
1448  *
1449  * gat_editModProps <command> <array> <module>
1450  *
1451  * Save or load properties about a module. "<command>" is either "load" or "save"
1452  *
1453  *****************************************************************************/
gat_editModProps(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1454 static int gat_editModProps(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1455 {
1456   char *aname = 0;
1457   char *mname = 0;
1458   GModuleDef *M;
1459 
1460   if (argc != 4) {
1461     Tcl_SetResult(tcl, "wrong number of arguments.", TCL_STATIC);
1462     return TCL_ERROR;
1463   }
1464 
1465   /* Tcl/Tk 8.3 wants non-const parameters to SetVar */
1466   aname = (char*)argv[2];
1467   mname = (char*)argv[3];
1468 
1469   M = env_findModule(mname);
1470   if (!M) {
1471     Tcl_SetVar2(tcl,aname,"ok","0",TCL_GLOBAL_ONLY);
1472     return TCL_OK;
1473   }
1474 
1475   if (strcmp(argv[1],"load") == 0) {
1476     GModuleDef_getPropsToTcl(M,tcl,aname);
1477   } else if (strcmp(argv[1],"save") == 0) {
1478     GModuleDef_setPropsFromTcl(M,tcl,aname);
1479     SetModified(MF_MODULE);
1480     SynchronizeInterface();
1481   } else {
1482     Tcl_SetResult(tcl, "bad command.", TCL_STATIC);
1483     return TCL_ERROR;
1484   }
1485 
1486   Tcl_SetVar2(tcl,aname,"ok","1",TCL_GLOBAL_ONLY);
1487 
1488   return TCL_OK;
1489 }
1490 
1491 /*****************************************************************************
1492  *
1493  *   Update net properties
1494  *
1495  *****************************************************************************/
gat_changeNet(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1496 static int gat_changeNet(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1497 {
1498   TkgGateWin *gw = TkGate.gw;
1499   EditState *es = gw->parms->circuit->es;
1500   const char *oldName = argv[1];
1501   const char *newName = argv[2];
1502   const char *vtype = argv[6];
1503   int hide = 0;
1504   int nbits = 1;
1505   int io = 0;
1506   GNet *n;
1507   GWire *w;
1508 
1509   if (GModuleDef_isDataProtected(TkGate.circuit->es->env)) {
1510     message(0,msgLookup("err.protdata"));		/* "Can not edit library module." */
1511     return TCL_OK;
1512   }
1513 
1514   sscanf(argv[3],"%d",&hide);
1515   sscanf(argv[4],"%d",&nbits);
1516   sscanf(argv[5],"%d",&io);
1517 
1518   n = (GNet*) SHash_find(es->env->m_nets,oldName);
1519 
1520   if (!n) return TCL_OK;
1521 
1522   w = n->n_driver;
1523   net_setSize(w->net,nbits);
1524   net_rename(n,newName,!hide);
1525   GNet_setVType(n, vtype);
1526 
1527   if (w->net->n_ionet) {
1528     GGateInfo *gi = GGateInfo_codeLookup(io);
1529     if (gi && (gi->code == GC_LOGICIN || gi->code == GC_LOGICOUT || gi->code == GC_LOGICTRI))
1530 	gate_transmute(w->net->n_ionet,gi);
1531   }
1532 
1533   FlagRedraw();
1534 
1535   return TCL_OK;
1536 }
1537 
gat_unselectGates(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1538 static int gat_unselectGates(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1539 {
1540   TkgGateWin *gw = TkGate.gw;
1541   EditState *es = gw->parms->circuit->es;
1542 
1543   EditState_unselectAll(es);
1544   return TCL_OK;
1545 }
1546 
1547 /*****************************************************************************
1548  *
1549  * Repalace a module instance with the current interface for a module and
1550  * attempt to reconnect all ports.  If the -all switch is given, then all instance
1551  * of the selected module are updated.
1552  *
1553  * Usage:
1554  *     gat_updateInterface [name]
1555  *     gat_updateInterface -all
1556  *
1557  *****************************************************************************/
gat_updateInterface(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1558 static int gat_updateInterface(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1559 {
1560   GCElement *g = TkGate.circuit->select;
1561   const char *modName = 0;
1562   GModuleDef *M = 0;
1563 
1564 
1565   if (argc == 1) {
1566     if (!g) return TCL_OK;
1567     if (GCElement_getType(g) != GC_BLOCK && GCElement_getType(g) != GC_SYMBLOCK) return TCL_OK;
1568     block_updateInterface(g, TkGate.circuit->es->env);
1569 
1570     return TCL_OK;
1571   }
1572 
1573   if (strcmp(argv[1],"-all") == 0) {
1574     if (DoTcl("tkg_getSelectedBlock") == TCL_OK && Tcl_GetStringResult(tcl)[0] != 0)
1575       modName = Tcl_GetStringResult(tcl);
1576     else if (g && (GCElement_getType(g) == GC_BLOCK || GCElement_getType(g) == GC_SYMBLOCK))
1577       modName = g->u.block.moduleName;
1578     else
1579       return TCL_OK;
1580   } else {
1581     modName = TkGate.circuit->es->env->m_name;
1582   }
1583 
1584   M = env_findModule(modName);
1585   if (!M) return TCL_OK;
1586 
1587   DoTcl("yesno [format [m circ.reallyupdate] %s]",GModuleDef_getName(M));
1588 
1589 
1590   /*
1591    * Scan circuit for instance of module M and update their interfaces.
1592    */
1593   if (strcmp(Tcl_GetStringResult(tcl),"yes") == 0) {
1594     Circuit *C =  TkGate.circuit;
1595     HashElem *he;
1596     for (he = Hash_first(C->moduleTable);he;he = Hash_next(C->moduleTable,he)) {
1597       GModuleDef *PM = (GModuleDef*)HashElem_obj(he);
1598       HashElem *ghe;
1599       for (ghe = Hash_first(PM->m_gates);ghe;ghe = Hash_next(PM->m_gates,ghe)) {
1600 	g = (GCElement*)HashElem_obj(ghe);
1601 	if ((GCElement_getType(g) == GC_BLOCK || GCElement_getType(g) == GC_SYMBLOCK) &&
1602 	    strcmp(g->u.block.moduleName,GModuleDef_getName(M)) == 0) {
1603 	  block_updateInterface(g, PM);
1604 	}
1605       }
1606     }
1607   }
1608 
1609   return TCL_OK;
1610 }
1611 
gat_updateModuleTree(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1612 static int gat_updateModuleTree(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1613 {
1614   SetModified(MF_MODULE);
1615   SynchronizeInterface();
1616 #if 0
1617   /* We now do this indirectly */
1618   env_updateMTCircuit();
1619 #endif
1620 
1621   return TCL_OK;
1622 }
1623 
gat_updateMenuState(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1624 static int gat_updateMenuState(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1625 {
1626   sel_updateMenuState();
1627   return TCL_OK;
1628 }
1629 
1630 
1631 
1632 
gat_setBlockDesc(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1633 static int gat_setBlockDesc(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1634 {
1635   GCElement *g = TkGate.circuit->select;
1636 
1637   if (tkgate_currentMode() != MM_EDIT) {
1638     message(0,msgLookup("err.editonly"));
1639     return TCL_OK;
1640   }
1641 
1642   if (g && g->typeinfo->code == GC_BLOCK) {
1643     GModuleDef *M = env_findAdd(g->u.block.moduleName,0);
1644     if (modint_setInterface(M,g) == 0)
1645       message(0,msgLookup("msg.setinterface"),g->u.block.moduleName);/* Set module interface for '%s'. */
1646   } else
1647     message(0,msgLookup("msg.needsel"));		/* Please select a module instance. */
1648 
1649   return TCL_OK;
1650 }
1651 
1652 /*****************************************************************************
1653  *
1654  * Begin interface edit mode
1655  *
1656  * If no argument are given, the current module is opened.  If a module name
1657  * is given then that interface is opened.
1658  *
1659  *****************************************************************************/
gat_editBlockDesc(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1660 static int gat_editBlockDesc(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1661 {
1662   TkgGateWin *gw = TkGate.gw;
1663   EditState **es = &gw->parms->circuit->es;
1664   GModuleDef *M = 0;
1665 
1666   if (argc > 1) {
1667     M = env_findAdd(argv[1],0);
1668   } else {
1669     M = (TkGate.circuit->root_mod == (*es)->env) ? 0 : (*es)->env;
1670   }
1671 
1672   if (tkgate_currentMode() == MM_EDIT && !TkGate.circuit->es->isInterface && hdl_checkSave(0) < 0)
1673     return TCL_OK;
1674 
1675   ob_touch(TkGate.circuit);
1676 
1677   modint_edit(es,M);
1678 
1679   return TCL_OK;
1680 }
1681 
gat_moveGate(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1682 static int gat_moveGate(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1683 {
1684   TkgGateWin *gw = TkGate.gw;
1685   EditState *es = gw->parms->circuit->es;
1686   int dx = 0,dy =0;
1687 
1688   assert(argc == 3);
1689 
1690   sscanf(argv[1],"%d",&dx);
1691   sscanf(argv[2],"%d",&dy);
1692 
1693   sel_draw(es);
1694   sel_move(es,dx,dy);
1695   sel_draw(es);
1696 
1697   return TCL_OK;
1698 }
1699 
gat_editNet(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1700 static int gat_editNet(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1701 {
1702   GNet *net;
1703   char buf[STRMAX],*p;
1704 
1705   if (tkgate_currentMode() != MM_EDIT) return TCL_OK;
1706 
1707   strcpy(buf,argv[1]);
1708   if ((p = strchr(buf,'['))) *p = 0;
1709   if ((p = strchr(buf,'@'))) *p = 0;
1710 
1711   net = GModuleDef_findNet(TkGate.circuit->es->env,buf);
1712   if (net && net->n_driver)
1713     net_editProps(net,net->n_driver->nodes->x,net->n_driver->nodes->y);
1714 
1715   return TCL_OK;
1716 }
1717 
1718 /****************************************************************************
1719  *
1720  * Get the selected object, append it to the cut buffer and delete the object
1721  * in the edit window.  Only usable for HDL.
1722  *
1723  * Usage: gat_CutToBufAppend
1724  *
1725  *****************************************************************************/
gat_cutToBufAppend(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1726 static int gat_cutToBufAppend(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1727 {
1728   TkgGateWin *gw = TkGate.gw;
1729   EditState *es = gw->parms->circuit->es;
1730 
1731   if (es->isInterface) {
1732     sel_interfaceReset(es);
1733   } else {
1734     sel_killAppend(es);
1735     FlagRedraw();
1736   }
1737 
1738   return TCL_OK;
1739 }
1740 
1741 /****************************************************************************
1742  *
1743  * Get the selected object, copy it to the cut buffer and delete the object
1744  * in the edit window.
1745  *
1746  * Usage: gat_cutToBuf
1747  *
1748  *****************************************************************************/
gat_cutToBuf(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1749 static int gat_cutToBuf(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1750 {
1751   TkgGateWin *gw = TkGate.gw;
1752   EditState *es = gw->parms->circuit->es;
1753 
1754   if (es->isInterface) {
1755     sel_interfaceReset(es);
1756   } else {
1757     sel_kill(es);
1758     FlagRedraw();
1759   }
1760 
1761   return TCL_OK;
1762 }
1763 
1764 /****************************************************************************
1765  *
1766  * Get the selected object and copy it to the cut buffer
1767  *
1768  * Usage: gat_copyToBuf
1769  *
1770  *****************************************************************************/
gat_copyToBuf(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1771 static int gat_copyToBuf(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1772 {
1773   TkgGateWin *gw = TkGate.gw;
1774   EditState *es = gw->parms->circuit->es;
1775 
1776   if (!es->isInterface)
1777     sel_copy(es);
1778 
1779   return TCL_OK;
1780 }
1781 
1782 /****************************************************************************
1783  *
1784  * Yank the object(s) from the cut buffer and paste it into the current module.
1785  *
1786  * Usage: gat_yankFromBuf [dx] [dy]
1787  *
1788  *
1789  *****************************************************************************/
gat_yankFromBuf(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1790 static int gat_yankFromBuf(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1791 {
1792   TkgGateWin *gw = TkGate.gw;
1793   EditState *es = gw->parms->circuit->es;
1794   /**
1795    * @TODO to remove
1796    */
1797   /* GModuleDef *m = es->env; */
1798   int dx,dy;
1799 
1800   if (!modifyOK(es,0)) return TCL_OK;
1801 
1802   if (hdl_isactive) {
1803     sel_hdlyank(es);
1804   } else {
1805     if (argc >= 3) {
1806       sscanf(argv[1],"%d",&dx);
1807       sscanf(argv[2],"%d",&dy);
1808 
1809       if (TkGate.circuit->cut_buffer) {
1810 	mark_unpost();
1811 	TkGate.ed->tx = TkGate.circuit->cut_buffer->cb_ctrx + dx;
1812 	TkGate.ed->ty = TkGate.circuit->cut_buffer->cb_ctry + dy;
1813       }
1814     }
1815     sel_yank(es);
1816     FlagRedraw();
1817   }
1818 
1819 
1820   return TCL_OK;
1821 }
1822 
1823 /*****************************************************************************
1824  *
1825  * Usage: gat_selectAll
1826  *
1827  * Select all gates in the current module
1828  *
1829  *****************************************************************************/
gat_selectAll(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1830 static int gat_selectAll(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1831 {
1832   TkgGateWin *gw = TkGate.gw;
1833   EditState *es = gw->parms->circuit->es;
1834 
1835   mark_unpost();
1836   sel_clear(es,1);
1837   sel_selectAll(es);
1838 
1839   EditState_setRotation(MODE_MOVESEL);
1840   return TCL_OK;
1841 }
1842 
1843 
1844 /*****************************************************************************
1845  *
1846  * Usage: gat_selectNet [name]
1847  *
1848  * Select the specified net in the current module
1849  *
1850  *****************************************************************************/
gat_selectNet(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1851 static int gat_selectNet(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1852 {
1853   TkgGateWin *gw = TkGate.gw;
1854   EditState *es = gw->parms->circuit->es;
1855   GModuleDef *m = es->env;
1856   GNet *n;
1857 
1858   if (argc != 2) {
1859     return TCL_OK;
1860   }
1861 
1862   n = GModuleDef_findNet(m,argv[1]);
1863   if (n) {
1864     net_select(n,1);
1865   }
1866 
1867   return TCL_OK;
1868 }
1869 
1870 /*****************************************************************************
1871  *
1872  * Usage: gat_rotate
1873  *
1874  * Rotates the gates in the selection.
1875  *
1876  *****************************************************************************/
gat_rotate(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1877 static int gat_rotate(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1878 {
1879   TkgGateWin *gw = TkGate.gw;
1880   EditState *es = gw->parms->circuit->es;
1881   int rdir = 1;
1882 
1883   if (argc >= 2) {
1884     sscanf(argv[1],"%d",&rdir);
1885     if (rdir < 0)
1886       rdir = -1;
1887     else
1888       rdir = 1;
1889   }
1890 
1891   if (!modifyOK(es,0)) return TCL_OK;
1892   if (tkgate_currentMode() != MM_EDIT) return TCL_OK;
1893   if (es->isInterface) return TCL_OK;
1894 
1895   sel_refinish(es);
1896 
1897   sel_draw(es);
1898   sel_rotate(es,rdir);
1899   sel_draw(es);
1900 
1901   return TCL_OK;
1902 }
1903 
1904 
1905 /*
1906   Check to see if breakpoint expression is valid.
1907 
1908   The first argument specifies the breakpoint operation to perform.
1909 
1910   -load				Load breakpoints into tk listbox
1911   -clear			Clear all breakpoints
1912   -replace n bp			Replace a breakpoint
1913   -insert n bp			Insert a breakpoint
1914   -delete n			Delete a breakpoint
1915 
1916   The 'replace' and 'insert' commands will return a negative value on error.
1917   Otherwise they will return the id number of the breakpoint.
1918  */
gat_breakpoint(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1919 static int gat_breakpoint(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1920 {
1921   NHash *bpm = TkGate.circuit->c_breakpoints;
1922   int i,r;
1923 
1924   r = 0;
1925 
1926 #if 0
1927   {
1928     for (i = 0;i < argc;i++)
1929       printf("%s ",argv[i]);
1930     printf("\n");
1931   }
1932 #endif
1933 
1934 
1935   if (strcmp(argv[1],"-load") == 0) {
1936     /*
1937      * Load breakpoints from internal state
1938      */
1939     BrkPtTable_loadInterface(bpm);
1940     r = 0;
1941   } else if (strcmp(argv[1],"-clear") == 0) {
1942     /*
1943      * Clear all breakpoints from internal state
1944      */
1945     BrkPtTable_clearStop(bpm);
1946   } else if (strcmp(argv[1],"-replace") == 0) {
1947     /*
1948      * Clear all breakpoints from internal state
1949      */
1950     if (sscanf(argv[2],"%d",&i) != 1) return -1;
1951     BrkPtTable_delete(bpm,i);
1952     r = BrkPtTable_insert(bpm,i,argv[3]);
1953   } else if (strcmp(argv[1],"-insert") == 0) {
1954     /*
1955      * Insert a new breakpoint
1956      */
1957     if (sscanf(argv[2],"%d",&i) != 1) return -1;
1958     r = BrkPtTable_insert(bpm,i,argv[3]);
1959   } else if (strcmp(argv[1],"-delete") == 0) {
1960     /*
1961      * Delete a new breakpoint
1962      */
1963     if (sscanf(argv[2],"%d",&i) != 1) return -1;
1964     BrkPtTable_delete(bpm,i);
1965     r = 0;
1966   } else if (strcmp(argv[1],"-enable") == 0) {
1967     /*
1968      * Delete a new breakpoint
1969      */
1970     if (sscanf(argv[2],"%d",&i) != 1) return -1;
1971     BrkPtTable_enable(bpm,i);
1972     r = 0;
1973   } else if (strcmp(argv[1],"-disable") == 0) {
1974     /*
1975      * Delete a new breakpoint
1976      */
1977     if (sscanf(argv[2],"%d",&i) != 1) return -1;
1978     BrkPtTable_disable(bpm,i);
1979     r = 0;
1980   }
1981 
1982   Tcl_SetObjResult(tcl, Tcl_NewIntObj(r));
1983   return TCL_OK;
1984 }
1985 
gat_simSelected(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])1986 static int gat_simSelected(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
1987 {
1988   GCElement *g = TkGate.circuit->select;
1989   int i;
1990   int match = 0;
1991 
1992   if (!g) {
1993     Tcl_ResetResult(tcl);
1994     return TCL_OK;
1995   }
1996 
1997   if (argc == 1)
1998     match = 1;
1999   else {
2000     for (i = 1;i < argc;i++)
2001       if (g->typeinfo == GGateInfo_vlookup(argv[i])) {
2002 	match = 1;
2003 	break;
2004       }
2005   }
2006 
2007   if (!match) {
2008     Tcl_ResetResult(tcl);
2009     return TCL_OK;
2010   }
2011 
2012   GSimModule_getFullPath(TkGate.circuit->es->smod,g,(char *)Tcl_GetStringResult(tcl));
2013 
2014   return TCL_OK;
2015 }
2016 
gat_print(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2017 static int gat_print(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2018 {
2019   int i;
2020   GPrintOpt PO;
2021 
2022   GPrintOpt_init(&PO);
2023 
2024   for (i = 1;i < argc;i+=2) {
2025     if (i+1 >= argc) break;
2026     if (strcmp(argv[i],"-printer") == 0)
2027       PO.po_cmd = argv[i+1];
2028     else if (strcmp(argv[i],"-file") == 0)
2029       PO.po_file = argv[i+1];
2030     else if (strcmp(argv[i],"-paper") == 0)
2031       PO.po_paper = argv[i+1];
2032     else if (strcmp(argv[i],"-orient") == 0)
2033       PO.po_orient = argv[i+1];
2034     else if (strcmp(argv[i],"-style") == 0)
2035       PO.po_style = argv[i+1];
2036     else if (strcmp(argv[i],"-select") == 0)
2037       PO.po_select = argv[i+1];
2038     else if (strcmp(argv[i],"-modlist") == 0)
2039       PO.po_modlist = argv[i+1];
2040     else if (strcmp(argv[i],"-index") == 0)
2041       PO.po_index = argv[i+1];
2042     else if (strcmp(argv[i],"-graph") == 0)
2043       PO.po_graph = argv[i+1];
2044     else if (strcmp(argv[i],"-epsf") == 0)
2045       PO.po_epsf = argv[i+1];
2046     else if (strcmp(argv[i],"-merge") == 0)
2047       PO.po_4up = argv[i+1];
2048     else if (strcmp(argv[i],"-duplex") == 0)
2049       PO.po_isDuplex = argv[i+1];
2050     else if (strcmp(argv[i],"-inclib") == 0)
2051       PO.po_incLib = argv[i+1];
2052   }
2053 
2054   GPrintOpt_print(&PO);
2055 
2056   return TCL_OK;
2057 }
2058 
gat_cleanUp(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2059 static int gat_cleanUp(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2060 {
2061   gateCleanUp();
2062   return TCL_OK;
2063 }
2064 
2065 
gat_tracePrint(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2066 static int gat_tracePrint(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2067 {
2068   int i;
2069   GPrintOpt PO;
2070 
2071   GPrintOpt_init(&PO);
2072 
2073   for (i = 1;i < argc;i+=2) {
2074     if (i+1 >= argc) break;
2075     if (strcmp(argv[i],"-printer") == 0)
2076       PO.po_cmd = argv[i+1];
2077     else if (strcmp(argv[i],"-file") == 0)
2078       PO.po_file = argv[i+1];
2079     else if (strcmp(argv[i],"-paper") == 0)
2080       PO.po_paper = argv[i+1];
2081     else if (strcmp(argv[i],"-orient") == 0)
2082       PO.po_orient = argv[i+1];
2083     else if (strcmp(argv[i],"-epsf") == 0)
2084       PO.po_epsf = argv[i+1];
2085     else if (strcmp(argv[i],"-duplex") == 0)
2086       PO.po_isDuplex = argv[i+1];
2087     else if (strcmp(argv[i],"-start") == 0)
2088       PO.po_start = argv[i+1];
2089     else if (strcmp(argv[i],"-end") == 0)
2090       PO.po_end = argv[i+1];
2091     else if (strcmp(argv[i],"-scalelength") == 0)
2092       PO.po_scaleLength = argv[i+1];
2093   }
2094 
2095   GPrintOpt_tracePrint(&PO);
2096 
2097   return TCL_OK;
2098 }
2099 
2100 /*
2101  * Get trace range data.  Returns a tripple of the form {sel_start sel_end trace_end}.
2102  */
gat_getTraceData(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2103 static int gat_getTraceData(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2104 {
2105   extern GScope *Scope;
2106   simtime_t start;
2107   simtime_t stop;
2108   simtime_t first = 0;
2109   int i;
2110   int did_first_set = 0;
2111   double timeCorrection;
2112 
2113   if (!Scope) {
2114     Tcl_SetResult(tcl, "0 0 0 0 ns 0", TCL_STATIC);
2115     return TCL_OK;
2116   }
2117 
2118   for (i = 0;i < Scope->NumTraces;i++) {
2119     GateValue *v;
2120     for (v = Scope->Traces[i]->t_first;v;v = v->v_next)
2121       if (v->v_code != VC_UNRECORDED)
2122 	break;
2123     if (v && (v->v_time < first || !did_first_set)) {
2124       first = v->v_time;
2125       did_first_set = 1;
2126     }
2127   }
2128 
2129 
2130   if (Scope->mark_count == 2) {
2131     start = Scope->mark_val[0];
2132     stop = Scope->mark_val[1];
2133   } else {
2134     start = Scope->s_leftTime;
2135     stop = Scope->s_leftTime+Scope->s_range;
2136   }
2137 
2138   if (start < first) start = first;
2139 
2140   if (stop < start) { int x = start; start = stop; stop = x; }
2141 
2142   start = imax(start,0);
2143   stop = imin(stop,Scope->s_time);
2144 
2145   timeCorrection = TkGate.circuit->simulator.si_tsmult/(double)Scope->s_precision;
2146 
2147   char res[128];
2148   sprintf(res,"%llu %llu %llu %lf %s %llu %llu",
2149 	  start,
2150 	  stop,
2151 	  Scope->s_range,
2152 	  timeCorrection,
2153 	  SimInterface_unitsToStr(TkGate.circuit->simulator.si_units),
2154 	  first,
2155 	  Scope->s_time);
2156   Tcl_SetResult(tcl, res, TCL_VOLATILE);
2157 
2158   return TCL_OK;
2159 }
2160 
gat_traceLPPEst(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2161 static int gat_traceLPPEst(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2162 {
2163   char paper[STRMAX];
2164   int i;
2165   const char *orient = "landscape";
2166   double lpp;
2167 
2168   for (i = 1;i < argc;i+=2) {
2169     if (i+1 >= argc) break;
2170 
2171     if (strcmp(argv[i],"-paper") == 0)
2172       sscanf(argv[i+1],"%s",paper);
2173     else if (strcmp(argv[i],"-orient") == 0)
2174       orient = argv[i+1];
2175   }
2176 
2177   lpp = traceLinesPerPage(orient, paper);
2178   Tcl_SetObjResult(tcl, Tcl_NewDoubleObj(lpp));
2179 
2180   return TCL_OK;
2181 }
2182 
2183 
gat_setCircProp(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2184 static int gat_setCircProp(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2185 {
2186   if (argc == 1) return TCL_OK;
2187 
2188   ob_touch(TkGate.circuit);
2189   ob_touch(TkGate.circuit->initScripts);
2190 
2191   if (strcmp(argv[1],"-clear") == 0) {
2192     int i;
2193 
2194     for (i = 0;i < TkGate.circuit->numInitScripts;i++)
2195       ob_free(TkGate.circuit->initScripts[i]);
2196     if (TkGate.circuit->initScripts)
2197       ob_free(TkGate.circuit->initScripts);
2198     TkGate.circuit->numInitScripts = 0;
2199     TkGate.circuit->initScripts = 0;
2200 
2201   } else if (strcmp(argv[1],"-script") == 0 && argc > 2) {
2202     if (TkGate.circuit->numInitScripts) {
2203       TkGate.circuit->initScripts = (char**) ob_realloc(TkGate.circuit->initScripts,sizeof(char*)*(TkGate.circuit->numInitScripts+1));
2204     } else
2205       TkGate.circuit->initScripts = (char**) ob_malloc(sizeof(char*),"char*");
2206     TkGate.circuit->initScripts[TkGate.circuit->numInitScripts++] = ob_strdup(argv[2]);
2207   } else if (strcmp(argv[1],"-vlib") == 0 && argc > 2) {
2208   } else if (strcmp(argv[1],"-top") == 0 && argc > 2) {
2209     GModuleDef *M = env_findModule(argv[2]);
2210     if (M)
2211       TkGate.circuit->root_mod = M;
2212   }
2213 
2214   return TCL_OK;
2215 }
2216 
gat_getCircProp(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2217 static int gat_getCircProp(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2218 {
2219   Tcl_ResetResult(tcl);
2220 
2221   if (strcmp(argv[1],"-script") == 0 && argc > 2) {
2222     int i;
2223 
2224     if (sscanf(argv[2],"%d",&i) != 1) return TCL_OK;
2225     if (i >= TkGate.circuit->numInitScripts) return TCL_OK;
2226     Tcl_SetResult(tcl, TkGate.circuit->initScripts[i], TCL_STATIC);
2227   }
2228 
2229   return TCL_OK;
2230 }
2231 
2232 /*****************************************************************************
2233  *
2234  * Get list of available locales
2235  *
2236  * Usage: gat_getLocales
2237  *
2238  * Returns a list of the form: {{English en} {Japanese ja} ... }
2239  *
2240  *****************************************************************************/
gat_getLocales(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2241 static int gat_getLocales(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2242 {
2243   int i;
2244   HashElem *he;
2245 
2246   Tcl_ResetResult(tcl);
2247 
2248   for (he = Hash_first(TkGate.localeTable), i = 0;he;he = Hash_next(TkGate.localeTable,he), i++) {
2249     char buf[STRMAX],buf2[STRMAX];
2250     Locale *l = (Locale*) HashElem_obj(he);
2251 
2252     sprintf(buf,"\"%s\" %s",quoteChars(buf2,l->l_name,TCL_SPECIALCHARS),l->l_code);
2253     Tcl_AppendElement(tcl,buf);
2254   }
2255 
2256   return TCL_OK;
2257 }
2258 
2259 /*****************************************************************************
2260  *
2261  * Set the value of a dip switch in simulation mode.
2262  *
2263  *****************************************************************************/
gat_setDip(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2264 static int gat_setDip(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2265 {
2266   GCElement *g;
2267   GSimSwitch *ss;
2268   GSimModule *M;
2269 
2270   if (argc != 3) return TCL_OK;
2271 
2272   char res[128];
2273   if (SimInterface_lookupGate(&TkGate.circuit->simulator,argv[1],&M,&g,&ss) == 0) {
2274 
2275     if (M == TkGate.circuit->es->smod) gate_draw(g,0);
2276 
2277     ob_touch(g);
2278     if (sscanf(argv[2],"%x",&g->u.sw.dipval) != 1) {
2279       g->u.sw.dipval = 0;
2280     }
2281 
2282     g->u.sw.dipval &= nmask(g->wires[DIP_OUT]->net->n_nbits);
2283 
2284     if (M == TkGate.circuit->es->smod) gate_draw(g,0);
2285 
2286     DoTcl("tkg_simNetSet %s %d'h%x",
2287 	  ss->name,
2288 	  g->wires[0]->net->n_nbits,
2289 	  g->u.sw.dipval);
2290 
2291     sprintf(res,"%x",g->u.sw.dipval);
2292   } else {
2293     sprintf(res,"0");
2294   }
2295 
2296   Tcl_SetResult(tcl, res, TCL_VOLATILE);
2297 
2298 
2299   return TCL_OK;
2300 }
2301 
2302 /*****************************************************************************
2303  *
2304  * Tcl procedure to do a text search
2305  *
2306  * Tcl syntax:
2307  *
2308  *   gat_find cmd [options]
2309  *
2310  * Commands are one of:
2311  *   search		Search for the next occurence of the target in the current context
2312  *   list		List all matches
2313  *   goto		Goto a specific match
2314  *
2315  *****************************************************************************/
gat_find(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2316 static int gat_find(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2317 {
2318   int mode = 0;
2319   int qualifier = 0;
2320   const char *target = 0;
2321   const char *command = 0;
2322   const char *variable = 0;
2323   int i;
2324 
2325   if (argc < 2) return TCL_ERROR;
2326 
2327   command = argv[1];
2328 
2329   for (i = 2;i < argc;i++)
2330     if (strcmp(argv[i],"-type") == 0 && i+1 < argc)
2331       sscanf(argv[++i],"%d",&mode);
2332     else if (strcmp(argv[i],"-qualifier") == 0 && i+1 < argc)
2333       sscanf(argv[++i],"%d",&qualifier);
2334     else if (strcmp(argv[i],"-target") == 0 && i+1 < argc)
2335       target = argv[++i];
2336     else if (strcmp(argv[i],"-variable") == 0 && i+1 < argc)
2337       variable = argv[++i];
2338 
2339   if (strcmp(command,"search") == 0) {
2340     if (!target) return TCL_OK;
2341     GSearchContext_find(TkGate.circuit->search,target,mode,qualifier);
2342   } else if (strcmp(command,"list") == 0) {
2343     if (!target || !variable) return TCL_OK;
2344     GSearchContext_list(TkGate.circuit->search,target,mode,qualifier,variable);
2345   } else if (strcmp(command,"goto") == 0) {
2346     if (argc > 2)
2347       GSearchContext_goto(argv[2]);
2348   }
2349 
2350   return TCL_OK;
2351 }
2352 
2353 /*****************************************************************************
2354  *
2355  * Format a time in epochs to use units (simulator must be active to use this)
2356  *
2357  * Tcl syntax:
2358  *
2359  *   gat_formatTime <time>
2360  *
2361  *****************************************************************************/
gat_formatTime(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2362 static int gat_formatTime(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2363 {
2364   simtime_t t;
2365   SimInterface *si = &TkGate.circuit->simulator;
2366 
2367   if (argc != 2) return TCL_ERROR;
2368   if (sscanf(argv[1],"%llu",&t) != 1) return TCL_ERROR;
2369 
2370   if (tkgate_currentMode() == MM_SIMULATE)
2371     SimInterface_formatTime(si, (char *)Tcl_GetStringResult(tcl), t);
2372   else
2373     Tcl_SetObjResult(tcl, Tcl_NewLongObj(t));
2374 
2375   return TCL_OK;
2376 }
2377 
2378 
gat_anchor(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2379 static int gat_anchor(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2380 {
2381   TkgGateWin *gw = TkGate.gw;
2382   EditState *es = gw->parms->circuit->es;
2383   int mode = 0;
2384   int old_mode;
2385 
2386   if (GModuleDef_isDataProtected(TkGate.circuit->es->env)) {
2387     message(0,msgLookup("err.protdata"));
2388     return TCL_OK;
2389   }
2390 
2391   if (TkGate.circuit->select)
2392     old_mode = TkGate.circuit->select->anchored;
2393   else if (TkGate.circuit->mg_selection)
2394     old_mode = TkGate.circuit->mg_selection->s_hasAnchored;
2395   else
2396     old_mode = 0;
2397 
2398   Tcl_SetObjResult(tcl, Tcl_NewIntObj(old_mode));
2399 
2400   if (argc > 1) {
2401     sscanf(argv[1],"%d",&mode);
2402     sel_anchor(es,mode);
2403   }
2404 
2405   return TCL_OK;
2406 }
2407 
gat_setcolors(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2408 static int gat_setcolors(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2409 {
2410   setGCcolors();
2411   FlagRedraw();
2412   if (tkgate_currentMode() == MM_SIMULATE)
2413     ReqScopeRedisplay();
2414 
2415   return TCL_OK;
2416 }
2417 
gat_scopeMotion(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2418 static int gat_scopeMotion(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2419 {
2420   int x = 0,y = 0,state = 0,n=1;
2421   int px =0,py = 0;
2422 
2423   if (argc < 7) return TCL_OK;
2424 
2425   sscanf(argv[1],"%d",&x);
2426   sscanf(argv[2],"%d",&y);
2427   sscanf(argv[3],"%d",&px);
2428   sscanf(argv[4],"%d",&py);
2429   sscanf(argv[5],"%d",&n);
2430   sscanf(argv[6],"%d",&state);
2431 
2432   scopeButtonMotion(x,y,px,py,n,state);
2433 
2434   return TCL_OK;
2435 }
2436 
gat_scopeButton(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2437 static int gat_scopeButton(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2438 {
2439   int x = 0,y = 0,state = 0,n=1;
2440   int px =0,py = 0;
2441 
2442   if (argc < 7) return TCL_OK;
2443 
2444   sscanf(argv[1],"%d",&x);
2445   sscanf(argv[2],"%d",&y);
2446   sscanf(argv[3],"%d",&px);
2447   sscanf(argv[4],"%d",&py);
2448   sscanf(argv[5],"%d",&n);
2449   sscanf(argv[6],"%d",&state);
2450 
2451   scopeButtonPress(x,y,px,py,n,state);
2452 
2453   return TCL_OK;
2454 }
2455 
gat_scopeRelease(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2456 static int gat_scopeRelease(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2457 {
2458   int x = 0,y = 0,state = 0,n=1;
2459   int px =0,py = 0;
2460 
2461   if (argc < 7) return TCL_OK;
2462 
2463   sscanf(argv[1],"%d",&x);
2464   sscanf(argv[2],"%d",&y);
2465   sscanf(argv[3],"%d",&px);
2466   sscanf(argv[4],"%d",&py);
2467   sscanf(argv[5],"%d",&n);
2468   sscanf(argv[6],"%d",&state);
2469 
2470   scopeButtonRelease(x,y,px,py,n,state);
2471 
2472   return TCL_OK;
2473 }
2474 
2475 /*****************************************************************************
2476  *
2477  * Tcl procedure to change the zoom level.
2478  *
2479  * Tcl syntax:
2480  *
2481  *   gat_zoom <zoom-change>
2482  *
2483  *****************************************************************************/
gat_zoom(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2484 static int gat_zoom(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2485 {
2486   int zoom = 0;
2487   int old_zf;
2488   int org_x, org_y;
2489 
2490   if (argc < 2) return TCL_OK;
2491 
2492   sscanf(argv[1],"%d",&zoom);
2493 
2494   old_zf = TkGate.circuit->zoom_factor;
2495   zoom = TkGate.circuit->zoom_factor + zoom;		/* The new zoom factor */
2496 
2497   if (zoom < 1 || zoom > ZOOM_MAX || zoom == TkGate.circuit->zoom_factor)
2498     return TCL_OK;
2499 
2500   ob_touch(TkGate.circuit);
2501   TkGate.circuit->zoom_factor = zoom;
2502   if (zoom == 1) {
2503     DoTcl("ToolBar::toolConfigure Zoom zoomout -state disabled");
2504     DoTcl("ToolBar::toolConfigure Zoom zoomin -state normal");
2505   } else if (zoom == ZOOM_MAX) {
2506     DoTcl("ToolBar::toolConfigure Zoom zoomout -state normal");
2507     DoTcl("ToolBar::toolConfigure Zoom zoomin -state disabled");
2508   } else {
2509     DoTcl("ToolBar::toolConfigure Zoom zoomout -state normal");
2510     DoTcl("ToolBar::toolConfigure Zoom zoomin -state normal");
2511   }
2512 
2513   org_x = TkGate.circuit->org_x - (TkGate.width/old_zf/2 - TkGate.width/TkGate.circuit->zoom_factor/2);
2514   org_y = TkGate.circuit->org_y - (TkGate.height/old_zf/2 - TkGate.height/TkGate.circuit->zoom_factor/2);
2515 
2516 #if 0
2517   printf("@zoom %dx%d  old=(%d,%d) new=(%d,%d)\n",TkGate.width,TkGate.height,TkGate.circuit->org_x,TkGate.circuit->org_y,org_x,org_y);
2518 #endif
2519 
2520   TkGate_setOrigin(org_x,org_y);
2521 
2522 
2523   if (TkGate.circuit->zoom_factor > 1) {
2524     XSetLineAttributes(TkGate.D,TkGate.moduleGC,TkGate.circuit->zoom_factor,LineSolid,CapButt,JoinMiter);
2525     XSetLineAttributes(TkGate.D,TkGate.instGC,TkGate.circuit->zoom_factor,LineSolid,CapButt,JoinMiter);
2526   } else {
2527     XSetLineAttributes(TkGate.D,TkGate.moduleGC,0,LineSolid,CapButt,JoinMiter);
2528     XSetLineAttributes(TkGate.D,TkGate.instGC,0,LineSolid,CapButt,JoinMiter);
2529   }
2530 
2531   XSetFont(TkGate.D, TkGate.instGC,		TkGate.textXF[zoom]->fid);
2532   XSetFont(TkGate.D, TkGate.moduleGC,		TkGate.textXF[zoom]->fid);
2533   XSetFont(TkGate.D, TkGate.modportGC,		TkGate.textXF[zoom]->fid);
2534   XSetFont(TkGate.D, TkGate.frameGC,		TkGate.textXF[zoom]->fid);
2535   XSetFont(TkGate.D, GatePainterContext_gc(TkGate.commentContext),TkGate.textXF[zoom]->fid);
2536   XSetFont(TkGate.D, TkGate.hyperlinkGC,	TkGate.textXF[zoom]->fid);
2537   XSetFont(TkGate.D, TkGate.wireGC,		TkGate.stextXF[zoom]->fid);
2538   XSetFont(TkGate.D, TkGate.busGC,		TkGate.stextXF[zoom]->fid);
2539   XSetFont(TkGate.D, TkGate.selWireGC,		TkGate.stextbXF[zoom]->fid);
2540   XSetFont(TkGate.D, TkGate.selBusGC,		TkGate.stextbXF[zoom]->fid);
2541   XSetFont(TkGate.D, TkGate.toolGC,		TkGate.textXF[zoom]->fid);
2542   XSetFont(TkGate.D, TkGate.cpathGC,		TkGate.textXF[zoom]->fid);
2543   if (TkGate.japaneseMode) {
2544     XSetFont(TkGate.D, TkGate.kanjiGC,		TkGate.ktextXF[zoom]->fid);
2545   }
2546 
2547   FlagRedraw();
2548 
2549   return TCL_OK;
2550 }
2551 
gat_align(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2552 static int gat_align(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2553 {
2554   TkgGateWin *gw = TkGate.gw;
2555   EditState *es = gw->parms->circuit->es;
2556   int x = 0;
2557 
2558   if (argc < 2) return TCL_OK;
2559 
2560   sscanf(argv[1],"%d",&x);
2561 
2562   if (x)
2563     sel_alignHorz(es);
2564   else
2565     sel_alignVert(es);
2566 
2567   return TCL_OK;
2568 }
2569 
2570 /*****************************************************************************
2571  *
2572  * Set location for a popup menu
2573  *
2574  * Tcl Syntax:
2575  *
2576  *    get_setpop x y
2577  *
2578  * Get ready to open a popup menu in the main edit window and return the type of
2579  * popup we should use based on the context.
2580  *
2581  *****************************************************************************/
gat_setpop(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2582 static int gat_setpop(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2583 {
2584   int x,y,cx,cy;
2585   GCElement *g = TkGate.circuit->select;
2586 
2587   x = y = 0;
2588   if (argc > 1) sscanf(argv[1],"%d",&x);
2589   if (argc > 2) sscanf(argv[2],"%d",&y);
2590 
2591   TkGate.popstate.g = g;
2592   TkGate.popstate.net = TkGate.circuit->nsel;
2593   TkGate.popstate.w = TkGate.circuit->wsel;
2594   TkGate.popstate.n = TkGate.circuit->wnsel;
2595   TkGate.popstate.wx = wtoc_x(x);
2596   TkGate.popstate.wy = wtoc_y(y);
2597   TkGate.popstate.x = wtoc_x(x/TkGate.circuit->zoom_factor);
2598   TkGate.popstate.y = wtoc_y(y/TkGate.circuit->zoom_factor);
2599 
2600 
2601   cx = TkGate.popstate.x;
2602   cy = TkGate.popstate.y;
2603 
2604   /*
2605    * If we are in simulate mode, use one of the simulate popups
2606    */
2607   if (tkgate_currentMode() == MM_SIMULATE) {
2608     if (g && GCElement_isModule(g))
2609       Tcl_SetResult(tcl, "blksimu", TCL_STATIC);
2610     else if (TkGate.popstate.n)
2611       Tcl_SetResult(tcl, "wiresimu", TCL_STATIC);
2612     else
2613       Tcl_SetResult(tcl, "simu", TCL_STATIC);
2614     return TCL_OK;
2615   }
2616 
2617   /*
2618    * If we are in analysis mode, use one of the analysis popups
2619    */
2620   if (tkgate_currentMode() == MM_ANALYZE) {
2621     if (g && GCElement_isModule(g))
2622       Tcl_SetResult(tcl, "blkanal", TCL_STATIC);
2623     else
2624       Tcl_SetResult(tcl, "anal", TCL_STATIC);
2625     return TCL_OK;
2626   }
2627 
2628   /*
2629    * If we are on the edit interfaces screen, use an edit interfaces popup
2630    */
2631   if (TkGate.circuit->es->isInterface) {
2632     if (g && GCElement_getType(g) == GC_BLOCK) {
2633       if (block_hitPort(g,cx,cy))
2634 	Tcl_SetResult(tcl, "intfblockport", TCL_STATIC);
2635       else if (block_edgehit(g,x,y))
2636 	Tcl_SetResult(tcl, "intfblockedge", TCL_STATIC);
2637       else
2638 	Tcl_SetResult(tcl, "intfblock", TCL_STATIC);
2639     } else if (g && GCElement_getType(g) == GC_SYMBLOCK) {
2640 	Tcl_SetResult(tcl, "intfblock", TCL_STATIC);
2641     } else
2642       Tcl_SetResult(tcl, "intf", TCL_STATIC);
2643 
2644     return TCL_OK;
2645   }
2646 
2647 
2648   if (EditState_getMode() != MODE_MOVE && EditState_getMode() != MODE_MOVESEL) {
2649     Tcl_SetResult(tcl, "notmove", TCL_STATIC);
2650     return TCL_OK;
2651   }
2652 
2653   if (TkGate.circuit->mg_selection && !g)
2654     Tcl_SetResult(tcl, "multi", TCL_STATIC);
2655   else if (g) {
2656     int N = GCElement_numPads(g);
2657     int can_add = 0;
2658     int i;
2659 
2660     for (i = 0;i < N;i++)
2661       if (GCElement_getPadCanAdd(g,i))
2662 	can_add = 1;
2663 
2664     if (g->typeinfo->code == GC_BLOCK) {
2665       if (block_hitPort(g,cx,cy))
2666         Tcl_SetResult(tcl, "blockport", TCL_STATIC);
2667       else if (block_edgehit(g,cx,cy))
2668         Tcl_SetResult(tcl, "blockedge", TCL_STATIC);
2669       else
2670         Tcl_SetResult(tcl, "block", TCL_STATIC);
2671     } else if (g->typeinfo->code == GC_SYMBLOCK) {
2672       Tcl_SetResult(tcl, "block", TCL_STATIC);
2673     } else if (g->typeinfo->code == GC_JOINT) {
2674       if (!g->wires[0] || !g->wires[1] || !g->wires[2] || !g->wires[3])
2675 	Tcl_SetResult(tcl, "joint3", TCL_STATIC);
2676       else
2677 	Tcl_SetResult(tcl, "joint4", TCL_STATIC);
2678     } else if (can_add)
2679       Tcl_SetResult(tcl, "MIgate", TCL_STATIC);
2680     else
2681       Tcl_SetResult(tcl, "gate", TCL_STATIC);
2682   } else if (TkGate.popstate.n) {
2683     char *labelCode = TkGate.popstate.n->isLabeled ? "L" : "";
2684     char *sizeCode = TkGate.popstate.n->showSize ? "S" : "";
2685 
2686     if (TkGate.popstate.net && TkGate.popstate.net->n_nbits > 1)
2687       Tcl_AppendResult(tcl, "mbwire", labelCode, sizeCode, NULL);
2688     else
2689       Tcl_AppendResult(tcl, "wire", labelCode, NULL);
2690   }
2691   else
2692     Tcl_SetResult(tcl, "canv", TCL_STATIC);
2693 
2694   /*     ob_touch(TkGate.popstate); (popstate may need to be made undoable?) */
2695 
2696   return TCL_OK;
2697 }
2698 
2699 /*****************************************************************************
2700  *
2701  * Tcl procedure to set the tkgate major mode.
2702  *
2703  * Parameters:
2704  *    _d		Client data (unused)
2705  *    tcl		Tcl interpreter
2706  *    argc		Number of arguments
2707  *    argv		Vector of arguments
2708  *
2709  * Returns:		Tcl status
2710  *
2711  * Tcl forms:
2712  *
2713  *   gat_setMajorMode <mode>
2714  *
2715  *****************************************************************************/
gat_setMajorMode(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2716 static int gat_setMajorMode(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2717 {
2718   int target_mode;
2719   int has_plus = 0;
2720 
2721   if (argc < 2) {
2722     Tcl_SetResult(tcl, "bad mode", TCL_STATIC);
2723     return TCL_ERROR;
2724   }
2725 
2726   if (!TkGate.circuit || !TkGate.circuit->es) return TCL_OK;
2727 
2728   if (strcmp(argv[1],"simulate") == 0) {
2729     target_mode = MM_SIMULATE;
2730   } else if (strcmp(argv[1],"+edit") == 0) {
2731     target_mode = MM_EDIT;
2732     has_plus = 1;
2733   } else if (strcmp(argv[1],"edit") == 0) {
2734     target_mode = MM_EDIT;
2735   } else if (strcmp(argv[1],"analyze") == 0) {
2736     target_mode = MM_ANALYZE;
2737   }  else {
2738     Tcl_SetResult(tcl, "bad mode", TCL_STATIC);
2739     return TCL_ERROR;
2740   }
2741 
2742 
2743   /*
2744    * If we are in normal edit mode, do an HDL save with checks before changing modes.
2745    */
2746 #if 0
2747   if (tkgate_currentMode() == MM_EDIT && target_mode != MM_EDIT
2748       && !TkGate.circuit->es->isInterface && hdl_checkSave(0) < 0)
2749     return TCL_OK;
2750 #endif
2751 
2752   tkgate_setMajorMode(target_mode);
2753   if (has_plus && TkGate.circuit->es->isInterface) {
2754     modint_close();
2755   }
2756 
2757   return TCL_OK;
2758 }
2759 
2760 /*****************************************************************************
2761  *
2762  * Tcl procedure to get the tkgate major mode.
2763  *
2764  * Parameters:
2765  *    _d		Client data (unused)
2766  *    tcl		Tcl interpreter
2767  *    argc		Number of arguments
2768  *    argv		Vector of arguments
2769  *
2770  * Returns:		Tcl status
2771  *
2772  * Tcl forms:
2773  *
2774  *   gat_getMajorMode
2775  *
2776  * Tcl Return:		name of the major mode
2777  *
2778  *****************************************************************************/
gat_getMajorMode(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2779 static int gat_getMajorMode(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2780 {
2781   if (argc != 1) {
2782     Tcl_SetResult(tcl, "illegal argument.", TCL_STATIC);
2783     return TCL_ERROR;
2784   }
2785 
2786   if (!TkGate.circuit || !TkGate.circuit->es) return TCL_OK;
2787 
2788   switch (tkgate_currentMode()) {
2789     case MM_SIMULATE :
2790       Tcl_SetResult(tcl, "simulate", TCL_STATIC);
2791       break;
2792     case MM_EDIT :
2793       if (editstate_isInterfaceMode())
2794         Tcl_SetResult(tcl, "interface", TCL_STATIC);
2795       else
2796         Tcl_SetResult(tcl, "edit", TCL_STATIC);
2797       break;
2798     case MM_ANALYZE :
2799       Tcl_SetResult(tcl, "analyze", TCL_STATIC);
2800       break;
2801   }
2802   return TCL_OK;
2803 }
2804 
gat_gotoCPathNet(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2805 static int gat_gotoCPathNet(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2806 {
2807   const char *p;
2808   GNet *n;
2809   int x,y;
2810   GWireNode *wn1,*wn2;
2811 
2812   if (argc < 2) {
2813     Tcl_SetResult(tcl, "bad cpath", TCL_STATIC);
2814     return TCL_ERROR;
2815   }
2816 
2817   Error_navigateToModule(&TkGate.circuit->es,argv[1]);
2818   editstate_setCurrent(TkGate.circuit->es);
2819   FlagRedraw();
2820 
2821   p = strrchr (argv[1],'.');
2822   if (p)
2823     p++;
2824   else
2825     p = argv[1];
2826 
2827   n = GModuleDef_findNet(TkGate.circuit->es->env,p);
2828   if (!n) {
2829     Tcl_AppendResult(tcl, "net '", p, "' not found.", NULL);
2830     return TCL_ERROR;
2831   }
2832 
2833   wn1 = n->n_driver->nodes;
2834   wn2 = wn1->out ? wn1->out : wn1->in;
2835   x = (wn1->x + wn2->x)/2;
2836   y = (wn1->y + wn2->y)/2;
2837 
2838   TkGate_setOrigin(TkGate.width/2 - x,TkGate.height/2 - y);
2839   ob_touch(TkGate.circuit->es);
2840   editstate_saveOrig(TkGate.circuit->es);
2841   SetErrorPosition(x,y);
2842 
2843   return TCL_OK;
2844 }
2845 
2846 /*****************************************************************************
2847  *
2848  * Handle commands changeing properties of a port on a block edge, or add a
2849  * port to a block edge.
2850  *
2851  * Usage: gat_popupPortCmd command [arg]
2852  *
2853  * Command List:
2854  *     add-in		Add an input port
2855  *     add-out		Add an output port
2856  *     add-inout	Add an inout port
2857  *     change-in	Change port type to input
2858  *     change-out	Change port type to output
2859  *     change-inout	Change port type to inout
2860  *     delete		Delete a port
2861  *     size n		Set bit size
2862  *
2863  *****************************************************************************/
gat_popupPortCmd(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2864 static int gat_popupPortCmd(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2865 {
2866   TkgGateWin *gw = TkGate.gw;
2867   EditState *es = gw->parms->circuit->es;
2868   GWire *w = 0;
2869 
2870   if (argc < 2) {
2871     Tcl_SetResult(tcl, "bad popup", TCL_STATIC);
2872     return TCL_ERROR;
2873   }
2874 
2875 #if TOUCH_XGATE_ED
2876   ob_touch(TkGate.ed);
2877 #endif
2878   TkGate.ed->tx = TkGate.popstate.x;
2879   TkGate.ed->ty = TkGate.popstate.y;
2880 
2881   /*
2882    * These commands are not applied to an existing port
2883    */
2884   if (strncmp(argv[1],"add-",4) == 0) {
2885     int iotype = strIOType(argv[1]+4);
2886     if (iotype >= 0)
2887       block_newport(es,iotype);
2888     return TCL_OK;
2889   }
2890 
2891   /*
2892    * All other command must be applied to a port.  Go try to find it.
2893    */
2894   if (TkGate.circuit->select && TkGate.circuit->select->typeinfo->code == GC_BLOCK)
2895     w = block_hitPort(TkGate.circuit->select,TkGate.ed->tx,TkGate.ed->ty);
2896 
2897   /*
2898    * Do nothing if we could not find a port (popup menu context testing should
2899    * prevent this from happening.
2900    */
2901   if (!w)
2902     return TCL_OK;
2903 
2904 
2905   if (strcmp(argv[1],"change-in") == 0) {
2906     block_setdir(w->nodes,es,IN);
2907   } else if (strcmp(argv[1],"change-out") == 0) {
2908     block_setdir(w->nodes,es,OUT);
2909   } else if (strcmp(argv[1],"change-inout") == 0) {
2910     block_setdir(w->nodes,es,TRI);
2911   } else if (strcmp(argv[1],"change") == 0) {
2912     block_changedir(w->nodes,es);
2913   } else if (strcmp(argv[1],"size") == 0) {
2914     int size;
2915     if (argc < 3 || sscanf(argv[2],"%d",&size) != 1) {
2916       Tcl_SetResult(tcl, "bad port size", TCL_STATIC);
2917       return TCL_ERROR;
2918     }
2919     GNet_draw(w->net);
2920     net_setSize(w->net,size);
2921     GNet_draw(w->net);
2922     SetModified(MF_INTERFACE);
2923     SynchronizeInterface();
2924   } else if (strcmp(argv[1],"delete") == 0) {
2925     if (w->gate && (w->gate->typeinfo->code == GC_BLOCK)) {
2926       SetModified(MF_NET);
2927       net_unselect(1);
2928       wire_cut(w->nodes->x,w->nodes->y,w->nodes, es->env);
2929       ob_touch(TkGate.circuit);
2930       TkGate.circuit->wsel = NULL;
2931       TkGate.circuit->wnsel = NULL;
2932     }
2933     SetModified(MF_INTERFACE);
2934     SynchronizeInterface();
2935   } else {
2936     Tcl_SetResult(tcl, "illegal port command.", TCL_STATIC);
2937     return TCL_ERROR;
2938   }
2939 
2940   return TCL_OK;
2941 }
2942 
gat_popupSetState(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2943 static int gat_popupSetState(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2944 {
2945   if (argc > 1)
2946     sscanf(argv[1],"%d",&TkGate.popstate.isSet);
2947   else
2948     Tcl_SetObjResult(tcl, Tcl_NewIntObj(TkGate.popstate.isSet));
2949 
2950   return TCL_OK;
2951 }
2952 
gat_popupWireProps(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2953 static int gat_popupWireProps(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2954 {
2955   GNet *net;
2956 
2957   net = TkGate.popstate.w->net;
2958   if (net) {
2959 #if TOUCH_XGATE_ED
2960     ob_touch(TkGate.ed);
2961 #endif
2962     TkGate.ed->tx = TkGate.popstate.wx;
2963     TkGate.ed->ty = TkGate.popstate.wy;
2964     net_editProps(net,TkGate.ed->tx,TkGate.ed->ty);
2965   }
2966 
2967   return TCL_OK;
2968 }
2969 
gat_popupWireAddStub(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2970 static int gat_popupWireAddStub(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2971 {
2972   TkgGateWin *gw = TkGate.gw;
2973   EditState *es = gw->parms->circuit->es;
2974 
2975   if (TkGate.popstate.g) {
2976     if (TkGate.popstate.g->typeinfo->code == GC_JOINT)
2977       joint_addstub(TkGate.popstate.g,es);
2978   } else
2979   wire_addstub(es,TkGate.popstate.x,TkGate.popstate.y);
2980 
2981   return TCL_OK;
2982 }
2983 
2984 /*****************************************************************************
2985  *
2986  * Hide or show the bit size on a wire segment
2987  *
2988  *****************************************************************************/
gat_popupWireSize(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])2989 static int gat_popupWireSize(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
2990 {
2991   if (TkGate.popstate.n && TkGate.popstate.w) {
2992     GWireNode *n = TkGate.popstate.n;
2993     GWire *w = TkGate.popstate.w;
2994 
2995     GWire_draw(w);
2996     ob_touch(n);
2997     n->showSize = !n->showSize;
2998     GWire_draw(w);
2999   }
3000 
3001 
3002   return TCL_OK;
3003 }
3004 
3005 /*****************************************************************************
3006  *
3007  * Hide or show the label on a wire segment
3008  *
3009  * Usage:
3010  *     gat_popupWireLabel 			Toggle label
3011  *     gat_popupWireLabel -show			Show label
3012  *     gat_popupWireLabel -hide			Hide This Label
3013  *     gat_popupWireLabel -hideall		Hide All Labels
3014  *     gat_popupWireLabel -clearall		Remove all labels
3015  *
3016  *****************************************************************************/
gat_popupWireLabel(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3017 static int gat_popupWireLabel(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3018 {
3019   GWireNode *n = TkGate.popstate.n;
3020   GWire *w = TkGate.popstate.w;
3021   GNet *net = TkGate.popstate.net;
3022   int y = TkGate.ed->ty;
3023   int x = TkGate.ed->tx;
3024   int isLabeled;
3025 
3026   if (!net || !n || !w)
3027     return TCL_OK;
3028 
3029   isLabeled = n->isLabeled;
3030 
3031   if (argc > 1) {
3032     if (strcmp(argv[1],"-hideall") == 0) {
3033       GNet_draw(net);
3034       GNet_hideName(net);
3035       GNet_draw(net);
3036       return TCL_OK;
3037     } else if (strcmp(argv[1],"-clearall") == 0) {
3038       GWire *wlist[GNet_numWires(net)];
3039       int count = GNet_getWires(net,wlist,GW_DRIVER);
3040       int i;
3041 
3042       GNet_draw(net);
3043       GNet_hideName(net);
3044       for (i = 0;i < count;i++) {
3045 	for (n = wlist[i]->nodes;n;n = n->out) {
3046 	  if (n->isLabeled) {
3047 	    ob_touch(n);
3048 	    n->isLabeled = 0;
3049 	  }
3050 	}
3051       }
3052       GNet_draw(net);
3053       return TCL_OK;
3054     } else if (strcmp(argv[1],"-show") == 0)
3055       isLabeled = 1;
3056     else if (strcmp(argv[1],"-hide") == 0)
3057       isLabeled = 0;
3058     else
3059       isLabeled = !isLabeled;
3060   }
3061 
3062   GNet_draw(net);
3063   ob_touch(n);
3064 
3065   n->isLabeled = isLabeled;
3066   if (n->isLabeled && n->out) {
3067     int offset = 50;
3068 
3069     if (n->y != n->out->y) {
3070       offset = 100*(y - n->y)/(n->out->y - n->y);
3071     } else if (n->x != n->out->x) {
3072       offset = 100*(x - n->x)/(n->out->x - n->x);
3073     }
3074     n->offset = offset;
3075 
3076     GNet_showName(net);
3077   }
3078   GNet_draw(net);
3079 
3080   return TCL_OK;
3081 }
3082 
3083 
gat_dumpWires(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3084 static int gat_dumpWires(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3085 {
3086   TkgGateWin *gw = TkGate.gw;
3087   EditState *es = gw->parms->circuit->es;
3088 
3089   wire_dump(es);
3090 
3091   return TCL_OK;
3092 }
3093 
gat_getTechList(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3094 static int gat_getTechList(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3095 {
3096   char **techs = GDelayDef_getTechList();
3097   int l,i;
3098 
3099   if (!techs) {
3100     Tcl_SetResult(tcl, TKGATE_DEFAULT_TECH, TCL_STATIC);
3101     return TCL_OK;
3102   }
3103 
3104   l = 0;
3105   for (i = 0;techs[i];i++)
3106     l += strlen(techs[i])+1;
3107   l++;
3108 
3109   for (i = 0;techs[i];i++)
3110     Tcl_AppendResult(tcl, " ", techs[i], NULL);
3111 
3112   return TCL_OK;
3113 }
3114 
3115 /*
3116   Set the technology for all selected gates.
3117  */
gat_setTech(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3118 static int gat_setTech(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3119 {
3120   TkgGateWin *gw = TkGate.gw;
3121   EditState *es = gw->parms->circuit->es;
3122 
3123   if (GModuleDef_isDataProtected(TkGate.circuit->es->env)) {
3124     message(0,msgLookup("err.protdata"));		/* "Can not edit library module." */
3125     return TCL_OK;
3126   }
3127 
3128   if (argc > 1) {
3129     ob_begin_frame("SetTech");
3130     sel_setTech(es,argv[1]);
3131     ob_end_frame();
3132   }
3133 
3134   return TCL_OK;
3135 }
3136 
3137 /*
3138   Get the technology of the selected gate
3139  */
gat_getTech(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3140 static int gat_getTech(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3141 {
3142   char *tech = 0;
3143 
3144   if (TkGate.circuit->select) {
3145     tech = TkGate.circuit->select->tech;
3146   } else if (TkGate.circuit->mg_selection) {
3147     HashElem *E;
3148     char *s_tech = 0;
3149 
3150     for (E = Hash_first(TkGate.circuit->mg_selection->s_gates);E;E = Hash_next(TkGate.circuit->mg_selection->s_gates,E)) {
3151       GCElement *g = (GCElement*) HashElem_obj(E);
3152       s_tech = g->tech ? g->tech : "";
3153       if (!tech)
3154 	tech = s_tech;
3155       else {
3156 	if (strcmp(tech,s_tech) != 0) {
3157 	  tech = "";
3158 	  break;
3159 	}
3160       }
3161     }
3162   }
3163 
3164   if (!tech) tech = "";
3165   Tcl_SetResult(tcl, tech, TCL_STATIC);
3166 
3167   return TCL_OK;
3168 }
3169 
gat_makeMakeMenu(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3170 static int gat_makeMakeMenu(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3171 {
3172   if (argc != 2) {
3173     Tcl_SetResult(tcl, "bad make menu", TCL_STATIC);
3174     return TCL_ERROR;
3175   }
3176 
3177   makeMakeMenu(argv[1]);
3178 
3179   return TCL_OK;
3180 }
3181 
3182 /*****************************************************************************
3183  *
3184  * Validate the suggested name of a port.
3185  *
3186  * gat_validatePortName module name orient dir nbits
3187  * gat_validatePortName module name orient dir nbits
3188  *
3189  *
3190  *****************************************************************************/
3191 int igen_strToSide(const char *side);
3192 void guessPortName(char *buf,GCElement *g,int orient,int dir,int nbits);
gat_validatePortName(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3193 static int gat_validatePortName(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3194 {
3195   /**
3196    * @TODO to remove
3197    */
3198   /*
3199   TkgGateWin *gw = TkGate.gw;
3200   EditState **es = &gw->parms->circuit->es;
3201   */
3202   GModuleDef *m = 0;
3203   const char *modName = 0;
3204   const char *oldPortName = 0;
3205   const char *newPortName = 0;
3206   char validName[STRMAX];
3207   SHash *curPorts = 0;
3208   int orient = 0;
3209   int dir = 0;
3210   int nbits = 0;
3211   const char *s;
3212 
3213   if (argc < 3) {
3214     Tcl_SetResult(tcl, "wrong number of parameters.", TCL_STATIC);
3215     return TCL_ERROR;
3216   }
3217 
3218   modName = argv[1];
3219   newPortName = argv[2];
3220   oldPortName = seekOption("-old",argv+3,argc-3);
3221 
3222   if ((s = seekOption("-dir",argv+3,argc-3))) {
3223     dir = strIOType(s);
3224   }
3225 
3226   if ((s = seekOption("-bits",argv+3,argc-3)))
3227     sscanf(s,"%d",&nbits);
3228 
3229   if ((s = seekOption("-orient",argv+3,argc-3))) {
3230     orient = igen_strToSide(s);
3231   }
3232 
3233   if (*modName)
3234     m = env_findModule(modName);
3235 
3236   if (m && m->m_interface) {
3237     GCElement *g = m->m_interface;
3238 
3239     if (g) {
3240       if (GCElement_getType(g) == GC_BLOCK) {
3241 	int N = GCElement_numPads(g);
3242 	GWire *w;
3243 	int i;
3244 
3245 	curPorts = new_SHash_noob();
3246 	for (i = 0;i < N;i++) {
3247 	  for (w = g->wires[i];w;w = w->next) {
3248 	    if (!oldPortName || strcmp(w->name,oldPortName) != 0) {
3249 	      SHash_insert(curPorts,w->name,w);
3250 	    }
3251 	  }
3252 	}
3253       } else if (GCElement_getType(g) == GC_SYMBLOCK) {
3254 	int N = GCElement_numPads(g);
3255 	GWire *w;
3256 	int i;
3257 
3258 	curPorts = new_SHash_noob();
3259 	for (i = 0;i < N;i++) {
3260 	  for (w = g->wires[i];w;w = w->next) {
3261 	    if (!oldPortName || strcmp(w->name,oldPortName) != 0) {
3262 	      SHash_insert(curPorts,w->name,w);
3263 	    }
3264 	  }
3265 	}
3266       }
3267       if (strcmp(newPortName,DEFAULT_PORT_NAME) == 0 || !*newPortName) {
3268 	guessPortName(validName,g,orient,dir,nbits);
3269 	newPortName = validName;
3270       }
3271     }
3272   }
3273 
3274   pickValidName(validName,newPortName,"P",curPorts);
3275 
3276   Tcl_SetResult(tcl, validName, TCL_VOLATILE);
3277 
3278   if (curPorts)
3279     delete_SHash(curPorts);
3280 
3281   return TCL_OK;
3282 }
3283 
3284 
gat_makeMakeShortcuts(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3285 static int gat_makeMakeShortcuts(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3286 {
3287   makeMakeShortcuts();
3288   return TCL_OK;
3289 }
3290 
gat_showPath(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3291 static int gat_showPath(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3292 {
3293   cpath_show(argc-1,argv+1);
3294   FlagRedraw();
3295   return TCL_OK;
3296 }
3297 
gat_clearPath(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3298 static int gat_clearPath(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3299 {
3300   cpath_clear();
3301   cpath_flush();
3302   FlagRedraw();
3303   return TCL_OK;
3304 }
3305 
gat_cpathFlash(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3306 static int gat_cpathFlash(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3307 {
3308   cpath_flash();
3309   return TCL_OK;
3310 }
3311 
gat_refreshScreen(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3312 static int gat_refreshScreen(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3313 {
3314   FlagRedraw();
3315   return TCL_OK;
3316 }
3317 
3318 
3319 /*
3320  * Verify that internal data structures are correct.
3321  */
gat_verify(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3322 static int gat_verify(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3323 {
3324   verify_circuit();
3325   return TCL_OK;
3326 }
3327 
3328 /*
3329  * Toggle the existence of a probe on the selected net.
3330  */
gat_toggleProbe(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3331 static int gat_toggleProbe(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3332 {
3333   char buf[STRMAX];
3334   char *netName = 0;
3335   SimInterface *si = &TkGate.circuit->simulator;
3336   GSimModule *SM;
3337   GWire *w;
3338   GNet *net;
3339   int x,y;
3340 
3341   if (tkgate_currentMode() != MM_SIMULATE)
3342     return TCL_OK;
3343 
3344   if (argc > 1) {
3345     GSimModule_getPathPrefix(TkGate.circuit->es->smod,buf);
3346     strcat(buf,argv[1]);
3347     netName = buf;
3348   } else if (TkGate.circuit->nsel) {
3349     GSimModule_getNetPathName(TkGate.circuit->es->smod,TkGate.circuit->nsel,buf);
3350     netName = buf;
3351   }
3352 
3353   if (!netName) {
3354     return TCL_OK;
3355   }
3356 
3357   if (SimInterface_lookupWire(si,netName,&SM,&w,&net) == 0) {
3358     if (w) {
3359       x = w->nodes->x;
3360       y = w->nodes->y;
3361       if (TkGate.popstate.isSet) {
3362 	x = TkGate.popstate.x;
3363 	y = TkGate.popstate.y;
3364 	GWire_pickProbePosition(TkGate.popstate.w,&x,&y);
3365       }
3366       SimInterface_addDelProbe(si,TkGate.circuit->es->smod,buf,w,w->nodes,x,y);
3367     } else {
3368       SimInterface_addDelHDLProbe(si,TkGate.circuit->es->smod,buf,net);
3369     }
3370   } else
3371     message(0,msgLookup("err.sim.nonet"),netName);
3372 
3373   return TCL_OK;
3374 }
3375 
gat_delScopeProbe(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3376 static int gat_delScopeProbe(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3377 {
3378   extern GScope *Scope;
3379   GScope_deleteSelectedTrace(Scope);
3380   return TCL_OK;
3381 }
3382 
3383 /*
3384  * Undo the last edit
3385  */
gat_undo(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3386 static int gat_undo(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3387 {
3388   int n = 1;
3389 
3390   if (argc > 1)
3391     sscanf(argv[1],"%d",&n);
3392 
3393   ob_undo(n);
3394   FlagRedraw();
3395   return TCL_OK;
3396 }
3397 
3398 /*
3399  * Redo the last undone edit
3400  */
gat_redo(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3401 static int gat_redo(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3402 {
3403   int n = 1;
3404 
3405   if (argc > 1)
3406     sscanf(argv[1],"%d",&n);
3407 
3408   ob_redo(n);
3409   FlagRedraw();
3410   return TCL_OK;
3411 }
3412 
gat_obBeginFrame(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3413 static int gat_obBeginFrame(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3414 {
3415   unsigned flags = 0;
3416 
3417   if (ob_get_mode() == OM_DISABLED) {
3418     Tcl_SetResult(tcl, "0", TCL_STATIC);
3419     return TCL_OK;
3420   }
3421 
3422   if (argc < 2) {
3423     abort();
3424     return TCL_OK;
3425   }
3426 
3427   if (argc > 2)
3428     sscanf(argv[2],"%u",&flags);
3429 
3430   if (strcmp(argv[1],"-") == 0)
3431     ob_begin_framef(0,flags);
3432   else
3433     ob_begin_framef(argv[1],flags);
3434 
3435   Tcl_SetResult(tcl, "1", TCL_STATIC);
3436 
3437   return TCL_OK;
3438 }
3439 
gat_obAppendFrame(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3440 static int gat_obAppendFrame(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3441 {
3442   if (argc != 2) return TCL_OK;
3443   if (strcmp(argv[1],"-") == 0)
3444     ob_append_frame(0);
3445   else
3446     ob_append_frame(argv[1]);
3447   return TCL_OK;
3448 }
3449 
gat_obEndFrame(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3450 static int gat_obEndFrame(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3451 {
3452   ob_end_frame();
3453   return TCL_OK;
3454 }
3455 
gat_getUndoList(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3456 static int gat_getUndoList(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3457 {
3458   const char *undoList[1024];
3459   int N,i;
3460 
3461   N = ob_getUndoList(undoList,1024);
3462 
3463   for (i = 0;i < N;i++)
3464     Tcl_AppendResult(tcl, " ", undoList[i], NULL);
3465 
3466   return TCL_OK;
3467 }
3468 
gat_getRedoList(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3469 static int gat_getRedoList(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3470 {
3471   const char *redoList[1024];
3472   int N,i;
3473 
3474   N = ob_getRedoList(redoList,1024);
3475 
3476   for (i = 0;i < N;i++)
3477     Tcl_AppendResult(tcl, " ", redoList[i], NULL);
3478 
3479   return TCL_OK;
3480 }
3481 
3482 /*****************************************************************************
3483  *
3484  * Return the current selection in the edit window.
3485  *
3486  * Parameters:
3487  *    _d		Client data (unused)
3488  *    tcl		Tcl interpreter
3489  *    argc		Number of arguments
3490  *    argv		Vector of arguments
3491  *
3492  * Returns:		Tcl status
3493  *
3494  * Tcl syntax:
3495  *
3496  *   gat_getSelected gates		Returns list of all selected element names
3497  *
3498  *   gat_getSelected module		Returns the selected module name if it is the only selection.
3499  *
3500  *   gat_getSelected			Same as "gates" option
3501  *
3502  *****************************************************************************/
gat_getSelected(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3503 static int gat_getSelected(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3504 {
3505   HashElem *E;
3506   GSelection *gs = TkGate.circuit->mg_selection;
3507   const char *what = "gates";
3508 
3509   if (argc > 1) what = argv[1];
3510 
3511   if (strcmp(what,"gates") == 0) {
3512     /*
3513      * WARNING: This function may not work correctly if there are a lot of gates
3514      * selected since the tcl->result buffer is not expanded as necessary.  However,
3515      * this features is not currently used, so it should not matter for now.
3516      */
3517     for (E = Hash_first(gs->s_gates);E;E = Hash_next(gs->s_gates,E)) {
3518       GCElement *g = (GCElement*) HashElem_obj(E);
3519       Tcl_AppendResult(tcl, " ", g->ename, NULL);
3520     }
3521   } else {
3522     if (sel_num(TkGate.circuit->es) == 1) {
3523       GCElement *g = TkGate.circuit->select;
3524 
3525       if (g && GCElement_isModule(g)) {
3526         Tcl_SetResult(tcl, g->u.block.moduleName, TCL_VOLATILE);
3527       }
3528     }
3529   }
3530 
3531   return TCL_OK;
3532 }
3533 
gat_obMode(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3534 static int gat_obMode(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3535 {
3536   ob_OMMode_t m = OM_ENABLED;
3537 
3538   if (argc == 1) {
3539     m = ob_get_mode();
3540     Tcl_SetObjResult(tcl, Tcl_NewIntObj(m));
3541   } else {
3542     sscanf(argv[1],"%d",(int*)&m);
3543     ob_set_mode(m);
3544   }
3545 
3546   return TCL_OK;
3547 }
3548 
gat_obFlush(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3549 static int gat_obFlush(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3550 {
3551   ob_clear();
3552   return TCL_OK;
3553 }
3554 
gat_obUnstick(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3555 static int gat_obUnstick(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3556 {
3557   ob_unstick();
3558   return TCL_OK;
3559 }
3560 
gat_setShowXHairState(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3561 static int gat_setShowXHairState(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3562 {
3563   int n;
3564 
3565   assert(argc == 2);
3566   sscanf(argv[1],"%d",&n);
3567 
3568   GScope_setShowXHairState(n);
3569 
3570   return TCL_OK;
3571 }
3572 
3573 /*****************************************************************************
3574  *
3575  * Called at the end of an editing action to cause internal circuit data to
3576  * be resynchronized with tcl interface data.
3577  *
3578  *****************************************************************************/
gat_syncInterface(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3579 static int gat_syncInterface(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3580 {
3581   SynchronizeInterface();
3582   return TCL_OK;
3583 }
3584 
gat_modintCenter(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3585 static int gat_modintCenter(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3586 {
3587   modint_center();
3588   return TCL_OK;
3589 }
3590 
3591 
3592 static int bit_width = 0;
3593 static int bit_height = 0;
3594 static unsigned **bit_data = 0;
3595 
3596 /*
3597  * Basic word size/byte size declarations.
3598  */
3599 #define SSWORDSIZE		TKGATE_WORDSIZE		/* # bits in an unsigned */
3600 #define SSWORDMASK		((unsigned)~0)		/* Word with all bits set */
3601 #if (SSWORDSIZE == 32)
3602 #define SSBITMASK		0x1f			/* Mask to get bit in word */
3603 #define SSWORDSHIFT		5			/* Shift to get word index */
3604 #define SSWORDBYTES		4			/* Number of bytes per word */
3605 #define SSHALFWORDMASK		0xffff			/* Mask for a half word */
3606 #elif (SSWORDSIZE == 64)
3607 #define SSBITMASK		0x3f			/* Mask to get bit in word */
3608 #define SSWORDSHIFT		6			/* Shift to get word index */
3609 #define SSWORDBYTES		8			/* Number of bytes per word */
3610 #define SSHALFWORDMASK		0xffffffff		/* Mask for a half word */
3611 #else
3612 #error Unsupported word size.
3613 #endif
3614 
Bit_extend(int x,int y)3615 static void Bit_extend(int x,int y)
3616 {
3617   x++; y++;
3618 
3619   if (x > bit_width) {
3620     int i;
3621 
3622     bit_width = x;
3623     for (i = 0;i < bit_height;i++)
3624       bit_data[i] = ob_realloc(bit_data[i],bit_width*sizeof(unsigned));
3625   }
3626 
3627   if (y > bit_height) {
3628     int i;
3629 
3630     if (bit_data)
3631       bit_data = ob_realloc(bit_data,y*sizeof(unsigned*));
3632     else
3633       bit_data = ob_malloc(y*sizeof(unsigned*),"unsigned*");
3634 
3635     for (i = bit_height;i < y;i++)
3636       bit_data[i] = ob_malloc(bit_width*sizeof(unsigned),"unsigned");
3637     bit_height = y;
3638   }
3639 }
3640 
3641 /*****************************************************************************
3642  *
3643  * Get bit data from bit buffer
3644  *
3645  * set data [gat_getBit x y]
3646  *
3647  *****************************************************************************/
gat_getBit(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3648 static int gat_getBit(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3649 {
3650   int x,y;
3651 
3652   sscanf(argv[1],"%d",&x);
3653   sscanf(argv[2],"%d",&y);
3654 
3655   Bit_extend(x,y);
3656 
3657   if ((bit_data[y][(x>>SSWORDSHIFT)] & (1 << (x & SSBITMASK))))
3658     Tcl_SetResult(tcl,"1",TCL_STATIC);
3659   else
3660     Tcl_SetResult(tcl,"0",TCL_STATIC);
3661 
3662   return TCL_OK;
3663 }
3664 
3665 /*****************************************************************************
3666  *
3667  * Set bit data in bit buffer
3668  *
3669  * gat_setBit x y d
3670  *
3671  *****************************************************************************/
gat_setBit(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3672 static int gat_setBit(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3673 {
3674   int x,y,d;
3675 
3676   sscanf(argv[1],"%d",&x);
3677   sscanf(argv[2],"%d",&y);
3678   sscanf(argv[3],"%d",&d);
3679 
3680   Bit_extend(x,y);
3681 
3682   if (d)
3683     bit_data[y][(x>>SSWORDSHIFT)] |= (1 << (x & SSBITMASK));
3684   else
3685     bit_data[y][(x>>SSWORDSHIFT)] &= ~(1 << (x & SSBITMASK));
3686 
3687   return TCL_OK;
3688 }
3689 
3690 /*****************************************************************************
3691  *
3692  * Exit tkgate
3693  *
3694  *****************************************************************************/
gat_exit(ClientData _d,Tcl_Interp * tcl,int argc,const char * argv[])3695 static int gat_exit(ClientData _d,Tcl_Interp *tcl,int argc,const char *argv[])
3696 {
3697   extern int exit_flag;
3698 
3699   exit_flag = 1;
3700 
3701   DoTcl("exit");
3702   return TCL_OK;
3703 }
3704 
3705 
3706 /*****************************************************************************
3707  *
3708  * Table of command names and handler functions for tkgate.
3709  *
3710  *****************************************************************************/
3711 static Tkg_Command tkg_procTable[] = {
3712   {"gat_addPort",		gat_addPort},
3713   {"gat_align",			gat_align},
3714   {"gat_analyzerCommand",	gat_analyzerCommand},
3715   {"gat_anchor",		gat_anchor},
3716   {"gat_batInc",		gat_batInc},
3717   {"gat_breakpoint",		gat_breakpoint},
3718   {"gat_changeNet",		gat_changeNet},
3719   {"gat_changePinDir",		gat_changePinDir},
3720   {"gat_claimBlock",		gat_claimBlock},
3721   {"gat_cleanUp",		gat_cleanUp},
3722   {"gat_clearPath",		gat_clearPath},
3723   {"gat_closeBox",		gat_closeBox},
3724   {"gat_computestrhash",	gat_computestrhash},
3725   {"gat_copyBlock",		gat_copyBlock},
3726   {"gat_copyToBuf",		gat_copyToBuf},
3727   {"gat_cpathFlash",		gat_cpathFlash},
3728   {"gat_cutToBuf",		gat_cutToBuf},
3729   {"gat_cutToBufAppend",	gat_cutToBufAppend},
3730   {"gat_debug",			gat_debug},
3731   {"gat_delScopeProbe",		gat_delScopeProbe},
3732   {"gat_deleteBlock",		gat_deleteBlock},
3733   {"gat_deleteSelected",	gat_deleteSelected},
3734   {"gat_dohyperlink",		gat_dohyperlink},
3735   {"gat_dumpWires",		gat_dumpWires},
3736   {"gat_editBlockDesc", 	gat_editBlockDesc},
3737   {"gat_editNet",		gat_editNet},
3738   {"gat_editProps",		gat_editProps},
3739   {"gat_editModProps",		gat_editModProps},
3740   {"gat_editCircProps",		gat_editCircProps},
3741   {"gat_errBoxReport",		gat_errBoxReport},
3742   {"gat_exit",			gat_exit},
3743   {"gat_find",			gat_find},
3744   {"gat_formatTime",		gat_formatTime},
3745   {"gat_getBit",		gat_getBit},
3746   {"gat_getCircProp",		gat_getCircProp},
3747   {"gat_getLocales",		gat_getLocales},
3748   {"gat_getMajorMode",		gat_getMajorMode},
3749   {"gat_getPrinterList",	gat_getPrinterList},
3750   {"gat_getRedoList",		gat_getRedoList},
3751   {"gat_getSelected",		gat_getSelected},
3752   {"gat_getTech",		gat_getTech},
3753   {"gat_getTechList",		gat_getTechList},
3754   {"gat_getTraceData",		gat_getTraceData},
3755   {"gat_getUndoList",		gat_getUndoList},
3756   {"gat_gotoCPathNet",		gat_gotoCPathNet},
3757   {"gat_hdl",			gat_hdl},
3758   {"gat_init",			gat_init},
3759   {"gat_interface",		gat_interface},
3760   {"gat_libIsLoaded",		gat_libIsLoaded},
3761   {"gat_load",			gat_load},
3762   {"gat_loadLibrary",		gat_loadLibrary},
3763   {"gat_loadMore",		gat_loadMore},
3764   {"gat_make",			gat_make},
3765   {"gat_makeMakeMenu",		gat_makeMakeMenu},
3766   {"gat_makeMakeShortcuts",	gat_makeMakeShortcuts},
3767   {"gat_mode",			gat_mode},
3768   {"gat_modintCenter",		gat_modintCenter},
3769   {"gat_moveGate",		gat_moveGate},
3770   {"gat_new",			gat_new},
3771   {"gat_newBlock",		gat_newBlock},
3772   {"gat_openBox",		gat_openBox},
3773   {"gat_obAppendFrame",		gat_obAppendFrame},
3774   {"gat_obBeginFrame",		gat_obBeginFrame},
3775   {"gat_obEndFrame",		gat_obEndFrame},
3776   {"gat_obFlush",		gat_obFlush},
3777   {"gat_obMode",		gat_obMode},
3778   {"gat_obUnstick",		gat_obUnstick},
3779   {"gat_popupPortCmd",		gat_popupPortCmd},
3780   {"gat_popupSetState",		gat_popupSetState},
3781   {"gat_popupWireProps",	gat_popupWireProps},
3782   {"gat_popupWireAddStub",	gat_popupWireAddStub},
3783   {"gat_popupWireLabel",	gat_popupWireLabel},
3784   {"gat_popupWireSize",		gat_popupWireSize},
3785   {"gat_print",			gat_print},
3786   {"gat_redo",			gat_redo},
3787   {"gat_refreshScreen",		gat_refreshScreen},
3788   {"gat_reinitDelay",		gat_reinitDelay},
3789   {"gat_renameBlock",		gat_renameBlock},
3790   {"gat_replicate",		gat_replicate},
3791   {"gat_reroot",		gat_reroot},
3792   {"gat_rotate",		gat_rotate},
3793   {"gat_saveCircuit",		gat_saveCircuit},
3794   {"gat_scopeButton",		gat_scopeButton},
3795   {"gat_scopeCommand",		gat_scopeCommand},
3796   {"gat_scopeMotion",		gat_scopeMotion},
3797   {"gat_scopeRelease",		gat_scopeRelease},
3798   {"gat_selectAll",		gat_selectAll},
3799   {"gat_selectNet",		gat_selectNet},
3800   {"gat_setBlockDesc",		gat_setBlockDesc},
3801   {"gat_setBit",		gat_setBit},
3802   {"gat_setCircProp",		gat_setCircProp},
3803   {"gat_setcolors",		gat_setcolors},
3804   {"gat_setDip",		gat_setDip},
3805   {"gat_setGateTechDelays",	gat_setGateTechDelays},
3806   {"gat_setMajorMode",		gat_setMajorMode},
3807   {"gat_setpop",		gat_setpop},
3808   {"gat_setShowXHairState",	gat_setShowXHairState},
3809   {"gat_setTech",		gat_setTech},
3810   {"gat_setrot",		gat_setrot},
3811   {"gat_showPath",		gat_showPath},
3812   {"gat_simSelected",		gat_simSelected},
3813   {"gat_syncInterface",		gat_syncInterface},
3814   {"gat_traceLPPEst",		gat_traceLPPEst},
3815   {"gat_tracePrint",		gat_tracePrint},
3816   {"gat_toggleProbe",		gat_toggleProbe},
3817   {"gat_undo",			gat_undo},
3818   {"gat_unloadLibrary",		gat_unloadLibrary},
3819   {"gat_unselectGates",		gat_unselectGates},
3820   {"gat_updateInterface",	gat_updateInterface},
3821   {"gat_updateModuleTree",	gat_updateModuleTree},
3822   {"gat_updateMenuState",	gat_updateMenuState},
3823   {"gat_validatePortName",	gat_validatePortName},
3824   {"gat_verify",		gat_verify},
3825   {"gat_yankFromBuf",		gat_yankFromBuf},
3826   {"gat_zoom",			gat_zoom},
3827 };
3828 static int tkg_procTableLen = sizeof(tkg_procTable)/sizeof(tkg_procTable[0]);
3829 
3830 /*****************************************************************************
3831  *
3832  * Tcl handler function initialization.
3833  *
3834  * Parameters:
3835  *      tcl		tcl interpreter handel
3836  *
3837  * Create entries for all of the tcl commands that are used by tkgate.
3838  *
3839  *****************************************************************************/
init_tclProcs(Tcl_Interp * tcl)3840 void init_tclProcs(Tcl_Interp *tcl)
3841 {
3842   int i;
3843 
3844   for (i = 0;i < tkg_procTableLen;i++) {
3845     Tcl_CreateCommand(tcl,tkg_procTable[i].command,tkg_procTable[i].func,0,0);
3846   }
3847 }
3848