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