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 Wed Mar 18 05:15:53 2009
19 ****************************************************************************/
20 
21 #ifdef __cplusplus
22 #include <cstdlib>
23 #include <cstdio>
24 #include <cstring>
25 #include <cassert>
26 #else
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <assert.h>
31 #endif
32 
33 #include <ctype.h>
34 #include <unistd.h>
35 
36 #include "tkgate.h"
37 #include "print.h"
38 
new_GModuleDef(const char * name)39 GModuleDef *new_GModuleDef(const char *name)
40 {
41   GModuleDef *M;
42 
43   M = OM_MALLOC(GModuleDef);
44 
45   M->m_name = ob_strdup(name);
46   M->m_fileName = 0;
47   M->m_libName = 0;
48   M->m_type = MT_NETLIST;
49   M->m_lineno = 0;
50   M->m_isLib = 0;
51   M->m_protData = 0;
52   M->m_protIntf = 0;
53   M->m_protEdit = 0;
54   M->m_hidden = 0;
55   M->m_used = 0;
56   M->m_isModload = 0;
57   M->m_isModsave = 0;
58   M->m_isSpecial = 0;
59   M->m_wires = NULL;
60   M->m_interface = 0;
61   M->m_altInterface = 0;
62   M->m_gates = new_SHash();
63   M->m_nets = new_SHash();
64   M->m_pptype = PPT_SCALED;
65   M->m_text = 0;
66   M->m_textSize = 0;
67   M->m_curLine = 0;
68   M->m_curChar = 0;
69   M->m_needScan = 1;
70   M->m_parmPorts = 0;
71 
72   /*
73    * If the module name begins with a '<' we assume this is a special
74    * module such as the cut buffer, interface list, or interface edit
75    * buffer.  Special modules do not appear in the list of modules and
76    * are only used internally.
77    */
78   if (*name == '<')
79     M->m_isSpecial = 1;
80 
81   return M;
82 }
83 
delete_GModuleDef(GModuleDef * M)84 void delete_GModuleDef(GModuleDef *M)
85 {
86   ob_touch(M);
87   env_clear(M);
88   ob_free(M->m_name);
89   delete_SHash(M->m_gates);
90   delete_SHash(M->m_nets);
91   if (M->m_text) ob_free(M->m_text);
92   if (M->m_parmPorts) delete_SHash(M->m_parmPorts);
93   ob_free(M);
94 }
95 
96 /*****************************************************************************
97  *
98  * Set the name of the library this module is from and mark it as a library module.
99  *
100  *****************************************************************************/
GModuleDef_setLibrary(GModuleDef * M,const char * name)101 void GModuleDef_setLibrary(GModuleDef *M,const char *name)
102 {
103   ob_touch(M);
104   M->m_libName = ob_strdup(name);
105   M->m_isLib = 1;
106 }
107 
GModuleDef_setFileName(GModuleDef * M,const char * name)108 void GModuleDef_setFileName(GModuleDef *M,const char *name)
109 {
110   ob_touch(M);
111   M->m_fileName = ob_strdup(name);
112 }
113 
GModuleDef_claim(GModuleDef * M)114 void GModuleDef_claim(GModuleDef *M)
115 {
116   ob_touch(M);
117   M->m_libName = 0;
118   M->m_isLib = 0;
119 }
120 
GModuleDef_findNet(GModuleDef * M,const char * name)121 GNet *GModuleDef_findNet(GModuleDef *M,const char *name)
122 {
123   return (GNet*) SHash_find(M->m_nets,name);
124 }
125 
GModuleDef_findGate(GModuleDef * M,const char * name)126 GCElement *GModuleDef_findGate(GModuleDef *M,const char *name)
127 {
128   return (GCElement*) SHash_find(M->m_gates,name);
129 }
130 
replicate_wirenodes(GWireNode * sn,int dx,int dy)131 static GWireNode *replicate_wirenodes(GWireNode *sn,int dx,int dy)
132 {
133   GWireNode *cn;
134 
135   if (!sn) return 0;
136 
137   cn = new_GWireNode();
138 
139   cn->x = sn->x + dx;
140   cn->y = sn->y + dy;
141   cn->showSize = sn->showSize;
142   cn->isLabeled = sn->isLabeled;
143   cn->labelSide = sn->labelSide;
144   cn->offset = sn->offset;
145 
146   cn->out = replicate_wirenodes(sn->out,dx,dy);
147 
148   if (cn->out) {
149     ob_touch(cn->out);
150     cn->out->in = cn;
151   }
152 
153   return cn;
154 }
155 
copyWireProps(GWire * nw,GWire * w)156 static void copyWireProps(GWire *nw,GWire *w)
157 {
158   ob_touch(nw);
159   nw->orient = w->orient;
160   nw->nidx = w->nidx;
161   nw->xanchor = w->xanchor;
162   nw->yanchor = w->yanchor;
163 }
164 
replicate_wire(GWire * w,GModuleDef * M,int dx,int dy)165 static GWire *replicate_wire(GWire *w,GModuleDef *M,int dx,int dy)
166 {
167   GWire *nw,*nw2,*ow;
168   GWireNode *n;
169 
170   ow = wire_other(w);
171 
172   nw = wire_newend(M,0,0);
173   nw2 = wire_newend(M,0,0);
174 
175   ob_touch(nw);
176   ob_touch(nw2);
177 
178   n = replicate_wirenodes(w->driver->nodes,dx,dy);
179 
180   nw->driver = nw;
181   nw2->driver = nw;
182   nw->wtype = DRIVER;
183   nw2->wtype = DRIVEE;
184 
185   nw->nodes = n;
186   while (n->out) n = n->out;
187   nw2->nodes = n;
188 
189   nw->nodes->end = nw;
190   nw2->nodes->end = nw2;
191 
192   if (w->driver != w) {
193     GWire *xw = nw;
194     nw = nw2;
195     nw2 = xw;
196   }
197 
198   copyWireProps(nw,w);
199   copyWireProps(nw2,ow);
200 
201   return nw;
202 }
203 
replicate_attachment(GWire * w,GCElement * ng,PHash * whash)204 static GWire *replicate_attachment(GWire *w,GCElement *ng,PHash *whash)
205 {
206   GWire *nw;
207 
208   if (!w) return 0;
209 
210   nw = (GWire*)PHash_find(whash,w);
211 
212   ob_touch(nw);
213 
214   if (!nw) {
215     logError(ERL_WARN,"Could not replicate attachment.");
216     return 0;
217   }
218 
219   nw->next = replicate_attachment(w->next,ng,whash);
220 
221   nw->offset.num = w->offset.num;
222   nw->offset.den = w->offset.den;
223   nw->WireDir = w->WireDir;
224   nw->PadNum = w->PadNum;
225   nw->invert = w->invert;
226   nw->gate = ng;
227   if (w->name) nw->name = ob_strdup(w->name);
228 
229   return nw;
230 }
231 
232 /*****************************************************************************
233  * Paste circuit in S into D.  Generally, S is a cut buffer and D is the
234  * current module (or vice versa).  The coordinates of the circuit in S
235  * is adjusted by the offset (dx, dy) as it is pasted.  If selOnly is
236  * set, then only seleced circuit elements are copied.  If selDst is
237  * set, then the pasted circuit elements are left as the current selection.
238  *****************************************************************************/
GModuleDef_copyInto(GModuleDef * D,GModuleDef * S,int dx,int dy,int selOnly,int selDst)239 void GModuleDef_copyInto(GModuleDef *D,GModuleDef *S,int dx,int dy,int selOnly,int selDst)
240 {
241 	HashElem *E;
242 
243 	PHash	*ghash;	/* Map from source gates to destination gates */
244 	PHash	*whash;	/* Map from source wires to destination wires */
245 	PHash	*nhash;	/* Map from source nets to destination nets */
246 	PHash	*rhash;	/* Map from destination nets to destination root wire */
247 
248 	GWire	*w;
249 	int	 i;
250 
251 	ghash = new_PHash();
252 	whash = new_PHash();
253 	nhash = new_PHash();
254 	rhash = new_PHash();
255 
256   /*
257     Create maps for gates, wires and nets
258    */
259   for (E = Hash_first(S->m_gates);E;E = Hash_next(S->m_gates,E)) {
260     GCElement *g,*ng;
261     int N;
262 
263     g = (GCElement*) HashElem_obj(E);
264     N = GCElement_numPads(g);
265     if (selOnly && !g->selected)
266       continue;
267 
268     ng = (*g->typeinfo->CopyGate)(D,g,g->xpos+dx,g->ypos+dy,REP_NOWIRES);
269 	PHash_insert(ghash,g,ng);
270 
271     ob_touch(ng);
272 
273     if (selDst) ng->selected = 1;
274 
275     for (i = 0;i < N;i++) {
276       for (w = g->wires[i];w;w = w->next) {
277 	if (!PHash_find(whash,w)) {
278 	  GWire *ow = wire_other(w);
279 	  GWire *nw = replicate_wire(w,D,dx,dy);
280 	  GWire *onw = wire_other(nw);
281 
282 	  PHash_insert(whash,w,nw);
283 	  PHash_insert(whash,ow,onw);
284 	}
285 
286 	if (!PHash_find(nhash,w->net)) {
287 	  GNet *n = w->net;
288 	  GNet *nn = new_GNet(n->n_signame,D);
289 
290 	  ob_touch(nn);
291 
292 	  nn->n_driver = (GWire*) PHash_find(whash,w);
293 	  nn->n_nbits = n->n_nbits;
294 	  nn->n_show_name = n->n_show_name;
295 
296 	  PHash_insert(nhash,w->net,nn);
297 	}
298       }
299     }
300   }
301 
302   /*
303    * Set nets of copied wires
304    */
305   for (E = Hash_first(whash);E;E = Hash_next(whash,E)) {
306     GWire *sw = (GWire*) PHashElem_key(E);
307     GWire *dw = (GWire*) HashElem_obj(E);
308     GNet *net = (GNet*) PHash_find(nhash,sw->net);
309     wire_setNet(dw,net);
310   }
311 
312   /*
313    * Attach wires to copied gates
314    */
315   for (E = Hash_first(ghash);E;E = Hash_next(ghash,E)) {
316     GCElement *g = (GCElement*) NHashElem_key(E);
317     GCElement *ng = (GCElement*) HashElem_obj(E);
318     int N = GCElement_numPads(g);
319     int i;
320 
321     ob_touch(ng);
322     for (i = 0;i < N;i++)
323       ng->wires[i] = replicate_attachment(g->wires[i],ng,whash);
324   }
325 
326 
327   /*
328    * Set i/o gates and finalize nets
329    */
330   for (E = Hash_first(nhash);E;E = Hash_next(nhash,E)) {
331     GNet *n = (GNet*) NHashElem_key(E);
332     GNet *nn = (GNet*) HashElem_obj(E);
333 
334     if (n->n_ionet)  {
335       ob_touch(nn);
336       nn->n_ionet = (GCElement*) PHash_find(ghash,n->n_ionet);
337     }
338 
339     wire_finalizeNet(nn->n_driver);
340   }
341 
342   /*
343    * Check for partitioned nets and make the partitions separate nets
344    * if any are found.
345    *
346    */
347   for (E = Hash_first(whash);E;E = Hash_next(whash,E)) {
348     GWire *dw = (GWire*) HashElem_obj(E);
349     GNet *net = dw->net;
350     GWire *rw = (GWire*) PHash_find(rhash,net);
351     GWire *dw_r;
352 
353     if (!rw) {
354       dw_r = rw = wire_sigroot(dw);
355       PHash_insert(rhash,net,rw);
356     } else
357       dw_r = wire_sigroot(dw);
358 #if 0
359     printf("PCHECK: %s",net->n_signame);
360     printf(" dw:{%d}(%x)",dw->nidx,dw);
361     printf(" dw_r:{%d}(%x)",dw_r->nidx,dw_r);
362     printf(" rw:{%d}(%x)",rw->nidx,rw);
363     printf(" nd:{%d}(%x)",net->driver->nidx,net->driver);
364     printf("\n");
365 #endif
366     if (rw != dw_r) {
367       GNet *nn = new_GNet(net->n_signame,D);
368 #if 0
369       printf("  nn:%s net:%s\n",nn->n_signame,net->n_signame);
370 #endif
371       ob_touch(nn);
372       nn->n_driver = dw_r;
373       nn->n_nbits = net->n_nbits;
374       nn->n_show_name = net->n_show_name;
375 
376       wire_setNet(dw_r,nn);
377 
378       wire_finalizeNet(dw_r);
379       wire_finalizeNet(net->n_driver);
380     }
381   }
382 
383   delete_PHash(rhash);
384   delete_PHash(nhash);
385   delete_PHash(whash);
386   delete_PHash(ghash);
387 }
388 
GModuleDef_numHdlLines(GModuleDef * M)389 int GModuleDef_numHdlLines(GModuleDef *M)
390 {
391   char *c;
392   int numLines = 1;
393 
394   if (GModuleDef_getType(M) == MT_NETLIST) return 0;
395 
396   for (c = M->m_text;*c;c++)
397     if (*c == '\n')
398 	numLines++;
399 
400   return numLines;
401 }
402 
GModuleDef_getBBX(GModuleDef * M,TargetDev_e target,int * minX,int * maxX,int * minY,int * maxY)403 void GModuleDef_getBBX(GModuleDef *M,TargetDev_e target, int *minX,int *maxX,int *minY,int *maxY)
404 {
405   if (GModuleDef_getType(M) == MT_NETLIST) {
406     HashElem *E;
407     GWireList *wl;
408     int is_first = 1;
409 
410     *minX = *maxX = *minY = *maxY = 0;
411 
412     for (E = Hash_first(M->m_gates);E;E = Hash_next(M->m_gates,E)) {
413       int g_minX,g_minY,g_maxX,g_maxY;
414 
415       GCElement *g = (GCElement*) HashElem_obj(E);
416 
417       gate_getbbx(g, target, &g_minX,&g_minY,&g_maxX,&g_maxY);
418       if (is_first || g_minX < *minX) *minX = g_minX;
419       if (is_first || g_minY < *minY) *minY = g_minY;
420       if (is_first || g_maxX > *maxX) *maxX = g_maxX;
421       if (is_first || g_maxY > *maxY) *maxY = g_maxY;
422       is_first = 0;
423     }
424 
425     for (wl = M->m_wires;wl;wl = wl->wl_next) {
426       GWire *w = wl->wl_wire;
427       GWireNode *n;
428 
429       if (!w->nodes->out) continue;
430 
431       for (n = w->nodes;n;n = n->out) {
432 	if (n->x < *minX) *minX = n->x;
433 	if (n->y < *minY) *minY = n->y;
434 	if (n->x > *maxX) *maxX = n->x;
435 	if (n->y > *maxY) *maxY = n->y;
436       }
437     }
438   } else {
439     extern HtmlFont hdl_font;
440     char *c,*s;
441     int maxLen = 0;
442     int numLines = 1;
443     int lineLen = 0;
444 
445     s = M->m_text;
446     for (c = M->m_text;*c;c++) {
447       if (*c == '\n') {
448 	numLines++;
449 	lineLen = PSStringWidth(&hdl_font,s,c-s);
450 	if (lineLen > maxLen) maxLen = lineLen;
451 	s = c+1;
452       }
453     }
454 
455     *minX = *minY = 0;
456     *maxX = maxLen;
457     *maxY = numLines*(int)(1.2*hdl_font.gateFont.size);
458   }
459 }
460 
GModuleDef_isRecursive_aux(GModuleDef * M,PHash * mhash)461 static GModuleDef *GModuleDef_isRecursive_aux(GModuleDef *M,PHash *mhash)
462 {
463   HashElem *E;
464   GModuleDef *R;
465 
466   if (PHash_find(mhash,M))
467     return M;
468   PHash_insert(mhash,M,(void*)1);
469 
470   for (E = Hash_first(M->m_gates);E;E = Hash_next(M->m_gates,E)) {
471     GCElement *g = (GCElement*) HashElem_obj(E);
472     if (GCElement_isModule(g)) {
473       GModuleDef *C = env_findModule(g->u.block.moduleName);
474       if (C) {
475 	R = GModuleDef_isRecursive_aux(C,mhash);
476 	if (R) return R;
477       }
478     }
479   }
480 
481   PHash_remove(mhash,M);
482 
483   return 0;
484 }
485 
486 /*
487  * Check to see if there are any recursive loops in M.  Returns null if
488  * no loops are found, and returns the offending module if one is found.
489  */
GModuleDef_isRecursive(GModuleDef * M)490 GModuleDef *GModuleDef_isRecursive(GModuleDef *M)
491 {
492   PHash *mhash;	/* set of modules we have seen so far. */
493   GModuleDef *R;
494 
495   mhash = new_PHash();
496   R = GModuleDef_isRecursive_aux(M,mhash);
497   delete_PHash(mhash);
498 
499   return R;
500 }
501 
502 /*****************************************************************************
503  *
504  * Returns non-zero if M contains any module instances.
505  *
506  *****************************************************************************/
GModuleDef_hasSubModules(GModuleDef * M)507 int GModuleDef_hasSubModules(GModuleDef *M)
508 {
509   HashElem *E;
510 
511   for (E = Hash_first(M->m_gates);E;E = Hash_next(M->m_gates,E)) {
512     GCElement *g = (GCElement*) HashElem_obj(E);
513     if (GCElement_isModule(g)) {
514       return 1;
515     }
516   }
517 
518   return 0;
519 }
520 
521 
GModuleDef_isDataProtected(GModuleDef * M)522 int GModuleDef_isDataProtected(GModuleDef *M)
523 {
524   return ((M)->m_protData || (M)->m_isLib);
525 }
526 
GModuleDef_isIntfProtected(GModuleDef * M)527 int GModuleDef_isIntfProtected(GModuleDef *M)
528 {
529   return M->m_protIntf || M->m_isLib || (M->m_protEdit && !editstate_isInterfaceMode());
530 }
531 
GModuleDef_flush(GModuleDef * M)532 void GModuleDef_flush(GModuleDef *M)
533 {
534   env_clear(M);
535   if (M->m_text) {
536     ob_free(M->m_text);
537     M->m_text = ob_strdup("");
538   }
539 }
540 
GModuleDef_getPropsToTcl(GModuleDef * M,Tcl_Interp * tcl,char * aname)541 void GModuleDef_getPropsToTcl(GModuleDef *M, Tcl_Interp *tcl,char *aname)
542 {
543   static char *modTypes[] = {"netlist", "hdl"};
544   char shortfile[STRMAX],*p;
545 
546   if (M->m_fileName) {
547     p = strrchr(M->m_fileName,'/');
548     if (p)
549       strcpy(shortfile,p+1);
550     else
551       strcpy(shortfile,M->m_fileName);
552   } else
553     strcpy(shortfile,"<new>");
554 
555 
556   Tcl_SetVar2(tcl,aname,"file",(M->m_fileName ? M->m_fileName : "") ,TCL_GLOBAL_ONLY);
557   Tcl_SetVar2(tcl,aname,"shortfile",shortfile,TCL_GLOBAL_ONLY);
558   Tcl_SetVar2(tcl,aname,"type",modTypes[M->m_type],TCL_GLOBAL_ONLY);
559   if (M->m_interface) {
560     if (GCElement_getType(M->m_interface) == GC_SYMBLOCK)
561       Tcl_SetVar2(tcl,aname,"itype","symbol",TCL_GLOBAL_ONLY);
562     else
563       Tcl_SetVar2(tcl,aname,"itype","block",TCL_GLOBAL_ONLY);
564   } else
565     Tcl_SetVar2(tcl,aname,"itype","block",TCL_GLOBAL_ONLY);
566 
567   Tcl_SetVar2(tcl,aname,"prot",binstr(M->m_protData),TCL_GLOBAL_ONLY);
568   Tcl_SetVar2(tcl,aname,"protint",binstr(M->m_protIntf),TCL_GLOBAL_ONLY);
569   Tcl_SetVar2(tcl,aname,"proted",binstr(M->m_protEdit),TCL_GLOBAL_ONLY);
570   Tcl_SetVar2(tcl,aname,"inuse","1",TCL_GLOBAL_ONLY);
571   Tcl_SetVar2(tcl,aname,"modload",binstr(M->m_isModload),TCL_GLOBAL_ONLY);
572   Tcl_SetVar2(tcl,aname,"modsave",binstr(M->m_isModsave),TCL_GLOBAL_ONLY);
573   Tcl_SetVar2(tcl,aname,"libname",(M->m_isLib ? M->m_libName : ""),TCL_GLOBAL_ONLY);
574   Tcl_SetVar2(tcl,aname,"wantclaim","0",TCL_GLOBAL_ONLY);
575   Tcl_SetVar2(tcl,aname,"ppos",(M->m_pptype == PPT_FIXED ? "fix" : "scale"),TCL_GLOBAL_ONLY);
576 }
577 
GModuleDef_setPropsFromTcl(GModuleDef * M,Tcl_Interp * tcl,char * aname)578 void GModuleDef_setPropsFromTcl(GModuleDef *M, Tcl_Interp *tcl,char *aname)
579 {
580   const char *r;
581 
582   ob_touch(M);
583   r = Tcl_GetVar2(tcl,aname,"prot",TCL_GLOBAL_ONLY);
584   M->m_protData = strbin(r);
585   r = Tcl_GetVar2(tcl,aname,"protint",TCL_GLOBAL_ONLY);
586   M->m_protIntf = strbin(r);
587   r = Tcl_GetVar2(tcl,aname,"proted",TCL_GLOBAL_ONLY);
588   M->m_protEdit = strbin(r);
589   Tcl_GetVar2(tcl,aname,"wantclaim",TCL_GLOBAL_ONLY);
590   r = Tcl_GetVar2(tcl,aname,"ppos",TCL_GLOBAL_ONLY);
591 
592   if (strcmp(r,"fix") == 0) {
593     M->m_pptype = PPT_FIXED;
594   } else
595     M->m_pptype = PPT_SCALED;
596 }
597 
GModuleDef_clearParmPorts(GModuleDef * M)598 void GModuleDef_clearParmPorts(GModuleDef *M)
599 {
600   if (M->m_parmPorts)
601     SHash_flush(M->m_parmPorts);
602 }
603 
GModuleDef_addParmPort(GModuleDef * M,const char * name,const char * value)604 void GModuleDef_addParmPort(GModuleDef *M,const char *name,const char *value)
605 {
606   if (!M->m_parmPorts) {
607     ob_touch(M);
608     M->m_parmPorts = new_SHash();
609   }
610 
611   SHash_insert(M->m_parmPorts, name, ob_strdup(value));
612 }
613 
614 /*****************************************************************************
615  *
616  * Scan an HDL module to find ports, wires and instances.
617  *
618  * Parameters:
619  *      M		Module to be scanned.
620  *
621  * Contact simulator to scan an HDL module for syntactical correctness and to
622  * retrieve basic data about the module.
623  *
624  *****************************************************************************/
GModuleDef_scanHDLModule(GModuleDef * M)625 int GModuleDef_scanHDLModule(GModuleDef *M)
626 {
627   char cmd[STRMAX],tempFile[STRMAX],data[STRMAX];
628   const char *r;
629   FILE *p,*f;
630   int has_module_mismatch = 0;
631   int count = 0;
632 
633 
634   r = Tcl_GetVar(TkGate.tcl,"simExec", TCL_GLOBAL_ONLY);
635   if (!r) return -1;
636 
637   M->m_needScan = 0;
638 
639   getSimTempFile(tempFile);
640 
641   sprintf(cmd,"%s -sq %s -D %lu",r,tempFile,computestrhash(tempFile));
642 
643   f = fopen(tempFile, "w");
644   if (!f) goto abortExit;
645 
646   VerilogSavePlainModule(f,M);
647   fclose(f);
648 
649   p = popen(cmd, "r");
650   if (!p) goto abortExit;
651 
652   env_clear(M);
653   GModuleDef_clearParmPorts(M);
654 
655   while (fgets(data, STRMAX, p)) {
656     char name[STRMAX],iname[STRMAX],msg[STRMAX];
657     int msb,lsb,n;
658 
659     if (sscanf(data," module %s",name) == 1) {
660       if (strcmp(name,M->m_name) != 0)
661 	has_module_mismatch = 1;
662       count++;
663     } else if (sscanf(data," line %d",&n) == 1) {
664       M->m_lineno = n;
665     } else if (sscanf(data," instance %s %s",name,iname) == 2) {
666 	GGateInfo *gi = GGateInfo_lookup("MODULE");
667 	GCElement *g;
668 
669 	if ((g = (*gi->MakeFunction)(0,M,gi->code,0,0,0,iname,1,0,0)))
670 	  g->u.block.moduleName = ob_strdup(name);
671     } else if (sscanf(data," input %s %d:%d",name,&msb,&lsb) == 3) {
672       GNet *n = new_GNet(name,M);
673       net_setDType(n,NT_INPUT);
674       net_setSize(n,msb-lsb+1);
675     } else if (sscanf(data," output %s %d:%d",name,&msb,&lsb) == 3) {
676       GNet *n = new_GNet(name,M);
677       net_setDType(n,NT_OUTPUT);
678       net_setSize(n,msb-lsb+1);
679     } else if (sscanf(data," inout %s %d:%d",name,&msb,&lsb) == 3) {
680       GNet *n = new_GNet(name,M);
681       net_setDType(n,NT_INOUT);
682       net_setSize(n,msb-lsb+1);
683     } else if (sscanf(data," wire %s %d:%d",name,&msb,&lsb) == 3) {
684       GNet *n = new_GNet(name,M);
685       net_setDType(n,NT_WIRE);
686       net_setSize(n,msb-lsb+1);
687     } else if (sscanf(data," reg %s %d:%d",name,&msb,&lsb) == 3) {
688       GNet *n = new_GNet(name,M);
689       net_setDType(n,NT_REG);
690       net_setSize(n,msb-lsb+1);
691     } else if (sscanf(data," parmport %s %[^\n]",name,msg) == 2) {
692       GModuleDef_addParmPort(M,name,msg);
693     } else if (sscanf(data," endmodule %s",name) == 1) {
694     } else if (sscanf(data," error %s %d %[^\n]",name,&n,msg) == 3) {
695     } else if (sscanf(data," warning %s %d %[^\n]",name,&n,msg) == 3) {
696     }
697   }
698 
699   pclose(p);
700 
701   if (count > 1)
702     message(MC_MSGLOG|MC_URGENT,msgLookup("err.modtoomany"),M->m_name);
703   else if (has_module_mismatch)
704     message(MC_MSGLOG|MC_URGENT,msgLookup("err.modmismatch"),M->m_name);
705 
706   return 0;
707 
708  abortExit:
709   unlink(tempFile);
710   return -1;
711 }
712 
713 /*****************************************************************************
714  *
715  * Make the empty module D a copy of module S.
716  *
717  *****************************************************************************/
GModuleDef_copy(GModuleDef * D,GModuleDef * S)718 void GModuleDef_copy(GModuleDef *D,GModuleDef *S)
719 {
720   GModuleDef_copyInto(D,S,0,0,0,0);
721 
722   if (S->m_type == MT_TEXTHDL) {
723 
724     D->m_type = MT_TEXTHDL;
725     D->m_lineno  = S->m_lineno;
726     if (D->m_text) ob_free(D->m_text);
727     GModuleDef_saveText(D,S->m_text);
728     D->m_curLine = S->m_curLine;
729     D->m_curChar = S->m_curChar;
730     D->m_needScan = 1;
731 
732     if (S->m_parmPorts) {
733       HashElem *he;
734 
735       D->m_parmPorts = new_SHash();
736       for (he = Hash_first(S->m_parmPorts);he;he = Hash_next(S->m_parmPorts,he))
737 	SHash_insert(D->m_parmPorts, SHashElem_key(he), ob_strdup((char*)HashElem_obj(he)));
738     }
739 
740 
741     hdl_replaceName(D,D->m_name);
742   }
743 }
744 
745 /*****************************************************************************
746  *
747  * Save text as the HDL text for a module.  Allocate new memory only if
748  * necessary.
749  *
750  *****************************************************************************/
GModuleDef_saveText(GModuleDef * M,const char * text)751 void GModuleDef_saveText(GModuleDef *M,const char *text)
752 {
753   int size = strlen(text) + 1;
754 
755   if (M->m_text) {
756     if (M->m_textSize >= size) {
757       ob_touch(M->m_text);
758       strcpy(M->m_text, text);
759       return;
760     } else
761       ob_free(M->m_text);
762   }
763   ob_touch(M);
764   M->m_text = ob_strdup(text);
765   M->m_textSize = size;
766 }
767 
768 /*****************************************************************************
769  *
770  * Make sure the text has space for at least n bytes in it.  Any existing
771  * text will be preserved.
772  *
773  *****************************************************************************/
GModuleDef_allocText(GModuleDef * M,int n)774 void GModuleDef_allocText(GModuleDef *M,int n)
775 {
776   if (M->m_text) {
777     if (M->m_textSize >= n) return;
778 
779     ob_touch(M);
780     M->m_text = (char*) ob_realloc(M->m_text, n);
781   } else {
782     ob_touch(M);
783     M->m_text = (char*) ob_malloc(n,"char*");
784   }
785   M->m_textSize = n;
786 }
787 
788 
GModuleDef_listPorts(GModuleDef * M)789 void GModuleDef_listPorts(GModuleDef *M)
790 {
791   GCElement *g = M->m_interface;
792 
793   DoTcl("PortList::flush");
794   if (g) {
795     int i;
796     int N = GCElement_numPads(g);
797     GWire *w;
798 
799     for (i = 0;i < N;i++) {
800       int dir = GCElement_getPadDir(g,i);
801       char *type = "";
802 
803       switch (dir) {
804       case IN  : type = "in"; break;
805       case OUT : type = "out"; break;
806       case TRI : type = "inout"; break;
807       }
808 
809       for (w = g->wires[i];w;w = w->next) {
810 	DoTcl("PortList::add %s -bits %d -type %s",w->name,w->net->n_nbits,type);
811       }
812     }
813   }
814 
815 }
816 
GModuleDef_listNets(GModuleDef * M)817 void GModuleDef_listNets(GModuleDef *M)
818 {
819   HashElem *nl;
820 
821   DoTcl("NetList::flush");
822   if (editstate_getInterfaceMode() == INTFMODE_NONE) {
823     for (nl = Hash_first(M->m_nets);nl;nl = Hash_next(M->m_nets,nl)) {
824       GNet *n = (GNet*) HashElem_obj(nl);
825       DoTcl("NetList::add %s -hidden %d -bits %d -type %s",n->n_signame,!n->n_show_name,n->n_nbits,GNet_getDTypeStr(n));
826     }
827   }
828 }
829 
830 /*****************************************************************************
831  *
832  * Test to see if we have selected a wire label.
833  *
834  *****************************************************************************/
GModuleDef_grabLabel(GModuleDef * m,int x,int y,GrabbedLabel * gl)835 int GModuleDef_grabLabel(GModuleDef *m,int x,int y,GrabbedLabel *gl)
836 {
837   GWireList *wl;
838 
839   for (wl = m->m_wires;wl;wl = wl->wl_next) {
840     GWire *w = wl->wl_wire;
841     GNet *net = w->net;
842     GWireNode *n;
843     int width = 0;
844 
845     if (!net->n_show_name) continue;
846 
847     for (n = w->nodes;n;n = n->out) {
848       int label_x,label_y,label_p;
849 
850       if (!n->isLabeled) continue;
851 
852       if (width == 0)
853 	width = GNet_getLabelWidth(net);
854       GWireNode_getLabelPos(n,net,&label_x,&label_y,&label_p);
855 
856       if (label_p & AtLeft) {
857 	if (x < label_x) continue;
858 	if (x > label_x + width) continue;
859       } else {
860 	if (x < label_x - width) continue;
861 	if (x > label_x) continue;
862       }
863 
864       if (label_p & AtBottom) {
865 	if (y > label_y) continue;
866 	if (y < label_y - 12) continue;
867       } else {
868 	if (y > label_y + 12) continue;
869 	if (y < label_y) continue;
870       }
871 
872       /*
873        * We found matching net so lets grab it.
874        */
875       ob_suggest_name("MoveLabel");
876       net_unselect(1);
877       EditState_unselectGate(TkGate.circuit->es);
878       GNet_draw(net);
879       net_select(net,0);
880       GrabbedLabel_set(net,label_x - x,label_y - y,label_p);
881       ob_touch(n);
882       n->isLabeled = 0;
883       n->labelSide = 0;
884       GNet_draw(net);
885       GrabbedLabel_draw(x,y);
886 
887       return 1;
888     }
889   }
890 
891   return 0;
892 }
893