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 #include "thyme.h"
19 
20 /*****************************************************************************
21  *
22  * Create a new declaration scope object
23  *
24  * Parameter:
25  *      s		Scope object to be initialized
26  *      parent		Parent scope
27  *
28  *****************************************************************************/
ScopeDecl_init(ScopeDecl * s,ScopeDecl * parent)29 void ScopeDecl_init(ScopeDecl *s,ScopeDecl *parent)
30 {
31   s->sd_parent = parent;
32   SHash_init(&s->sd_nets);
33 }
34 
35 /*****************************************************************************
36  *
37  * Uninitialize a declaration scope object
38  *
39  * Parameter:
40  *      s		Scope object to be uninitialized
41  *
42  *****************************************************************************/
ScopeDecl_uninit(ScopeDecl * s)43 void ScopeDecl_uninit(ScopeDecl *s)
44 {
45   SHash_uninit(&s->sd_nets);
46 }
47 
48 
new_Scope(const char * path,Scope * parent,ModuleInst * mi)49 Scope *new_Scope(const char *path,Scope *parent,ModuleInst *mi)
50 {
51   Scope *s = (Scope*) malloc(sizeof(Scope));
52 
53   Scope_init(s,path,parent,mi);
54 
55   return s;
56 }
57 
delete_Scope(Scope * s)58 void delete_Scope(Scope *s)
59 {
60   Scope_uninit(s);
61   free(s);
62 }
63 
Scope_init(Scope * s,const char * path,Scope * parent,ModuleInst * mi)64 void Scope_init(Scope *s,const char *path,Scope *parent,ModuleInst *mi)
65 {
66   s->s_path = path ? strdup(path) : 0;
67   s->s_parent = parent;
68   s->s_instance = mi;
69   s->s_peer = 0;
70   SHash_init(&s->s_nets);
71   SHash_init(&s->s_tasks);
72 }
73 
Scope_uninit(Scope * s)74 void Scope_uninit(Scope *s)
75 {
76   if (s->s_path) free(s->s_path);
77   SHash_uninit(&s->s_nets);
78   SHash_uninit(&s->s_tasks);
79 }
80 
Scope_setPeer(Scope * s,Scope * peer)81 void Scope_setPeer(Scope *s,Scope *peer)
82 {
83   s->s_peer = peer;
84 }
85 
Scope_findNet(Scope * s,const char * name,unsigned flags)86 Net *Scope_findNet(Scope *s,const char *name,unsigned flags)
87 {
88   Circuit *c = &vgsim.vg_circuit;		/* Top-level circuit */
89   Net *n = 0;
90 
91   /*
92    * If scope is null, look only for fully qualified names.
93    */
94   if (!s)
95     return Circuit_findNet(c,name);
96 
97   /*
98    * Look for 'name' in local name table.
99    */
100   n = (Net*) SHash_find(&s->s_nets,name);
101   if (n) return n;
102 
103   /*
104    * Look for 'name' in parent scope
105    */
106   if (s->s_parent && !(flags & SDF_LOCAL_ONLY))
107     n = Scope_findNet(s->s_parent,name,flags);
108   if (n) return n;
109 
110   /*
111    * Look for 'name' in peer module.
112    */
113   if (s->s_peer)
114     return  Scope_findNet(s->s_peer,name,flags);
115 
116   /*
117    * Look for 'name' as a fully qualified net name.
118    */
119   n = Circuit_findNet(c,name);
120   if (n) return n;
121 
122   if (strchr(name,'.')) {
123     char *tempName = (char*)malloc(strlen(s->s_path)+strlen(name)+2);
124     sprintf(tempName,"%s.%s",s->s_path,name);
125     n = Circuit_findNet(c,tempName);
126     free(tempName);
127   }
128 
129   return n;
130 }
131 
Scope_defNet(Scope * s,const char * name,Net * n)132 void Scope_defNet(Scope *s,const char *name,Net *n)
133 {
134   Circuit *c = &vgsim.vg_circuit;		/* Top-level circuit */
135 
136   SHash_insert(&s->s_nets,name,n);
137   SHash_insert(&c->c_nets,n->n_name,n);
138 }
139 
Scope_replaceLocalNet(Scope * s,const char * name,Net * n)140 void Scope_replaceLocalNet(Scope *s,const char *name,Net *n)
141 {
142   SHash_replace(&s->s_nets,name,n);
143 }
144 
145 
Scope_findTask(Scope * s,const char * name)146 UserTask *Scope_findTask(Scope *s,const char *name)
147 {
148   return (UserTask*)SHash_find(&s->s_tasks,name);
149 }
150 
Scope_defineTask(Scope * s,const char * name,UserTask * ut)151 int Scope_defineTask(Scope *s,const char *name,UserTask *ut)
152 {
153   if (Scope_findTask(s,name)) return -1;
154 
155   SHash_insert(&s->s_tasks,name,ut);
156 
157   return 0;
158 }
159 
Scope_findParm(Scope * scope,const char * name)160 Value *Scope_findParm(Scope *scope,const char *name)
161 {
162   Net *n = (Net*) Scope_findNet(scope,name,SDF_LOCAL_ONLY);
163   if (!n) return 0;
164   if (!(Net_getType(n) & NT_P_PARAMETER)) return 0;
165 
166   return Net_getValue(n);
167 }
168 
169 /*****************************************************************************
170  *
171  * Find a net in a declaration scope object
172  *
173  * Parameter:
174  *      s		Scope object to be uninitialized
175  *      name		Name of net to look for
176  *      flags		Flags modifying net lookup
177  *
178  *****************************************************************************/
ScopeDecl_findNet(ScopeDecl * s,const char * name,unsigned flags)179 NetDecl *ScopeDecl_findNet(ScopeDecl *s,const char *name,unsigned flags)
180 {
181   NetDecl *n;
182 
183   n = (NetDecl*) SHash_find(&s->sd_nets,name);
184   if (!n && s->sd_parent && !(flags & SDF_LOCAL_ONLY))
185     n = ScopeDecl_findNet(s->sd_parent,name,flags);
186 
187   return n;
188 }
189 
190 /*****************************************************************************
191  *
192  * Define a new net in a declaration scope
193  *
194  * Parameter:
195  *      s		Scope object to be uninitialized
196  *      n		Net declaration object to add
197  *
198  *****************************************************************************/
ScopeDecl_defNet(ScopeDecl * s,NetDecl * n)199 void ScopeDecl_defNet(ScopeDecl *s,NetDecl*n)
200 {
201   SHash_insert(&s->sd_nets,n->n_name,n);
202 }
203 
204 /*****************************************************************************
205  *
206  * Create a new module declaration object
207  *
208  * Parameter:
209  *      name		Name of the module
210  *
211  * Returns:		Newly create module object.
212  *
213  *****************************************************************************/
new_ModuleDecl(const char * name)214 ModuleDecl *new_ModuleDecl(const char *name)
215 {
216   ModuleDecl *m = (ModuleDecl*) malloc(sizeof(ModuleDecl));
217 
218   m->m_name = name ? strdup(name) : 0;
219   m->m_errorsDone = 0;
220   m->m_specify = 0;
221   List_init(&m->m_ports);
222   List_init(&m->m_parmPorts);
223   List_init(&m->m_items);
224   ScopeDecl_init(&m->m_scope,0);
225   SHash_init(&m->m_tasks);
226   m->m_faninnodes = 0;
227 
228   m->m_timescale = currentTimescale;
229 
230   return m;
231 }
232 
233 /*****************************************************************************
234  *
235  * Delete a module declaration object and reclaim all memory.
236  *
237  * Parameter:
238  *      m		Module declaration to be destroyed.
239  *
240  *****************************************************************************/
delete_ModuleDecl(ModuleDecl * m)241 void delete_ModuleDecl(ModuleDecl *m)
242 {
243   free(m->m_name);
244   List_uninit(&m->m_ports);
245   List_uninit(&m->m_parmPorts);
246   ScopeDecl_uninit(&m->m_scope);
247   SHash_uninit(&m->m_tasks);
248   if (m->m_specify) delete_Specify(m->m_specify);
249   free(m);
250 }
251 
252 /*****************************************************************************
253  *
254  * Add a port to a module declaration
255  *
256  * Parameter:
257  *      m		Module declaration to which to add port
258  *      name		Name of port to add
259  *
260  *****************************************************************************/
ModuleDecl_addPort(ModuleDecl * m,const char * name)261 void ModuleDecl_addPort(ModuleDecl *m,const char *name)
262 {
263   List_addToTail(&m->m_ports,strdup(name));
264 }
265 
266 /*****************************************************************************
267  *
268  * Define a 'parameter' in a module
269  *
270  * Parameter:
271  *      m		Module in which to define parameter
272  *      name		Name of the parameter
273  *      e		Expression for the parameter
274  *      isPort		Non-zero if this is a parameter port.
275  *
276  *****************************************************************************/
ModuleDecl_defineParm(ModuleDecl * m,const char * name,Expr * e,int isPort)277 void ModuleDecl_defineParm(ModuleDecl *m,const char *name,Expr *e, int isPort)
278 {
279   MIParameter *mip = new_MIParameter(name,e);
280 
281   List_addToTail(&m->m_items, mip);
282 
283   if (isPort) {
284     mip->mip_ppPos = List_numElems(&m->m_parmPorts);
285     List_addToTail(&m->m_parmPorts,strdup(name));
286   }
287 }
288 
ModuleDecl_isParm(ModuleDecl * m,const char * name)289 int ModuleDecl_isParm(ModuleDecl *m,const char *name)
290 {
291   ListElem *le;
292 
293   for (le = List_first(&m->m_parmPorts);le;le = List_next(&m->m_parmPorts,le)) {
294     const char *portName = (const char*)ListElem_obj(le);
295     if (strcmp(name,portName) == 0) return 1;
296   }
297   return 0;
298 }
299 
300 /*****************************************************************************
301  *
302  * Print basic information about a module definition.
303  *
304  * Parameters:
305  *     m		Module to display.
306  *
307  *****************************************************************************/
ModuleDecl_printData(ModuleDecl * m)308 void ModuleDecl_printData(ModuleDecl *m)
309 {
310   ListElem *le;
311 
312   printf("module %s\n",ModuleDecl_getName(m));
313   printf("  line %d\n",m->m_place.p_lineNo);
314 
315   for (le = List_first(&m->m_items);le;le = List_next(&m->m_items,le)) {
316     ModuleItem *mi = (ModuleItem*) ListElem_obj(le);
317 
318     switch (mi->mi_type) {
319     case IC_PARAMETER :
320       {
321 	MIParameter *mip = (MIParameter*) mi;
322 	ListElem *le2;
323 	for (le2 = List_first(&m->m_parmPorts);le2;le2 = List_next(&m->m_parmPorts,le2)) {
324 	  char *parmPort = (char*) ListElem_obj(le2);
325 	  if (strcmp(parmPort,mip->mip_name) == 0) break;
326 	}
327 	/* If parameter is parmport ... */
328 	if (le2) {
329 	  Value *v = Expr_parmEval(mip->mip_expr,0,PEF_NONE);
330 	  if (v) {
331 	    char buf[STRMAX];
332 	    Value_getstr(v,buf);
333 	    printf("  parmport %s %s\n",mip->mip_name,buf);
334 	  } else
335 	    printf("  parmport %s 0\n",mip->mip_name);
336 	}
337 
338 
339       }
340       break;
341     case IC_NETDECL :
342       {
343 	NetDecl *nd = mi->mi_netdec.mid_decl;
344 	int rangeok = 1;
345 	char typeName[STRMAX],rangeExpr[STRMAX];
346 	VRange *range;
347 
348 	if ((NetDecl_getType(nd) & NT_P_IO_MASK)) {
349 	  NT_getStr((NetDecl_getType(nd) & NT_P_IO_MASK)|NT_P_WIRE, typeName);
350 	} else if ((NetDecl_getType(nd) & NT_P_WIRE)) {
351 	  strcpy(typeName,"wire");
352 	} else if ((NetDecl_getType(nd) & NT_P_REG)) {
353 	  strcpy(typeName,"reg");
354 	} else
355 	  break;	/* ignore this type */
356 
357 	range = NetDecl_getRange(nd);
358 	if (VRange_getDirect(range,rangeExpr) < 0)
359 	  rangeok = 0;
360 
361 	printf("  %s %s %s\n",typeName, NetDecl_getName(nd),rangeExpr);
362 	if (!rangeok) {
363 	    errorFile(ModuleItem_getPlace(mi),ERR_BADPRTRANGE,NetDecl_getName(nd));
364 	}
365       }
366       break;
367     case IC_INSTANCE :
368       printf("  instance %s %s\n",mi->mi_inst.mii_name, mi->mi_inst.mii_instName);
369       break;
370     default :
371       break;
372     }
373   }
374 
375   printf("endmodule %s\n",ModuleDecl_getName(m));
376 }
377 
378 /*****************************************************************************
379  *
380  * Print a module declaration (for debugging purposes)
381  *
382  * Parameters:
383  *      m		Module declaration to print
384  *      f		File in which to print declaration
385  *
386  *****************************************************************************/
ModuleDecl_print(ModuleDecl * m,FILE * f)387 void ModuleDecl_print(ModuleDecl *m,FILE *f)
388 {
389   fprintf(f,"module %s",m->m_name);
390 
391   /*
392    * Display the parameter ports
393    */
394   if (List_numElems(&m->m_parmPorts) > 0) {
395     ListElem *E;
396     int notFirst = 0;
397 
398     fprintf(f," #(");
399     for (E = List_first(&m->m_parmPorts);E;E = List_next(&m->m_parmPorts,E)) {
400       const char *name = (const char*) ListElem_obj(E);
401       if (notFirst) fprintf(f,", ");
402       notFirst = 1;
403       fprintf(f,"%s",name);
404     }
405     fprintf(f,")");
406   }
407 
408   /*
409    * Display the ports
410    */
411   if (List_numElems(&m->m_ports) > 0) {
412     ListElem *E;
413     int notFirst = 0;
414 
415     fprintf(f," (");
416     for (E = List_first(&m->m_ports);E;E = List_next(&m->m_ports,E)) {
417       const char *name = (const char*) ListElem_obj(E);
418       if (notFirst) fprintf(f,", ");
419       notFirst = 1;
420       fprintf(f,"%s",name);
421     }
422     fprintf(f,")");
423   }
424   fprintf(f,";\n");
425 
426 
427   /*
428    * Display the items.
429    */
430   if (List_numElems(&m->m_items) > 0) {
431     ListElem *E;
432 
433     for (E = List_first(&m->m_items);E;E = List_next(&m->m_items,E)) {
434       ModuleItem *mi = (ModuleItem*) ListElem_obj(E);
435 
436       if (mi->mi_type != IC_NETDECL && mi->mi_type != IC_PARAMETER)
437 	fprintf(f,"\n");
438 
439       ModuleItem_print(mi,f);
440     }
441   }
442 
443   fprintf(f,"\n");
444   fprintf(f,"endmodule\n");
445 }
446 
ModuleDecl_findNet(ModuleDecl * m,const char * name)447 NetDecl *ModuleDecl_findNet(ModuleDecl *m,const char *name)
448 {
449   return ScopeDecl_findNet(&m->m_scope,name,0);
450 }
451 
452 /*****************************************************************************
453  *
454  * Add a net declaration to a module.
455  *
456  * Parameters:
457  *     m		Module declaration object
458  *     n		Net declaration object
459  *
460  *****************************************************************************/
ModuleDecl_defNet(ModuleDecl * m,NetDecl * n)461 void ModuleDecl_defNet(ModuleDecl *m,NetDecl*n)
462 {
463   ScopeDecl_defNet(&m->m_scope,n);
464   List_addToTail(&m->m_items, new_MINetDecl(n));
465 }
466 
467 /*****************************************************************************
468  *
469  * Create the specify data object for a module if not already created.
470  *
471  * Parameters:
472  *     m		Module declaration object
473  *
474  *****************************************************************************/
ModuleDecl_makeSpecify(ModuleDecl * m)475 void ModuleDecl_makeSpecify(ModuleDecl *m)
476 {
477   if (!m->m_specify)
478     m->m_specify = new_Specify(m);
479 }
480 
ModuleDecl_numPorts(ModuleDecl * m,nettype_t ptype)481 int ModuleDecl_numPorts(ModuleDecl *m,nettype_t ptype)
482 {
483   ListElem *le;
484   int n = 0;
485 
486   ptype &= NT_P_IO_MASK;
487 
488   for (le = List_first(&m->m_ports);le;le = List_next(&m->m_ports,le)) {
489     char *name = (char*)ListElem_obj(le);
490     NetDecl *nd = (NetDecl*)ModuleDecl_findNet(m,name);
491     if (nd && ((NetDecl_getType(nd) & NT_P_IO_MASK) == ptype))
492       n++;
493   }
494 
495   return n;
496 }
497 
ModuleDecl_findTask(ModuleDecl * m,const char * name)498 UserTaskDecl *ModuleDecl_findTask(ModuleDecl *m,const char *name)
499 {
500   return (UserTaskDecl*)SHash_find(&m->m_tasks,name);
501 }
502 
ModuleDecl_defineTask(ModuleDecl * m,const char * name,UserTaskDecl * utd)503 int ModuleDecl_defineTask(ModuleDecl *m,const char *name,UserTaskDecl *utd)
504 {
505   if (ModuleDecl_findTask(m,name)) return -1;
506 
507   SHash_insert(&m->m_tasks,name,utd);
508 
509   return 0;
510 }
511 
512 /*****************************************************************************
513  *
514  * Make an array of strings from the keys of the elements in a hash tabe
515  *
516  *****************************************************************************/
getHashKeys(SHash * H)517 static char **getHashKeys(SHash *H)
518 {
519   char **keys = (char **) malloc(sizeof(char*)*(Hash_numElems(H)+1));
520   HashElem *he;
521   int i = 0;
522 
523   for (he = Hash_first(H);he;he = Hash_next(H,he)) {
524     const char *name = SHashElem_key(he);
525     keys[i++] = strdup(name);
526   }
527   keys[i] = 0;
528 
529   return keys;
530 }
531 
532 #if 0
533 static void printHList(SHash *H)
534 {
535   HashElem *he;
536   int is_first = 1;
537 
538   for (he = Hash_first(H);he;he = Hash_next(H,he)) {
539     const char *name = SHashElem_key(he);
540     if (!is_first) printf(", ");
541     printf("%s",name);
542     is_first = 0;
543   }
544 }
545 #endif
546 
547 /*****************************************************************************
548  *
549  * Sort the itemlist in a module to be in topological order (used for path-delay modules)
550  *
551  * Parameters:
552  *      m		Module to be sorted
553  *
554  *****************************************************************************/
ModuleDecl_makeFaninTree(ModuleDecl * m)555 int ModuleDecl_makeFaninTree(ModuleDecl *m)
556 {
557   ListElem *le;
558   int i;
559 
560 #if 0
561   printf("ModuleDecl_makeFaninTree(%s)\n",m->m_name);
562 #endif
563   m->m_faninnodes = new_SHash();
564 
565 
566   for (le = List_first(&m->m_items);le; le = List_next(&m->m_items,le)) {
567     ModuleItem *item = (ModuleItem*) ListElem_obj(le);
568 
569     switch (item->mi_type) {
570     default :
571 #if 0
572       printf("   mitem\n");
573 #endif
574       break;
575     case IC_ASSIGN :
576       {
577 	MIAssign *a = (MIAssign*) item;
578 	FaninNode *fn = new_FaninNode(item);
579 	SHash outH,inH;
580 
581 	SHash_init(&outH);
582 	SHash_init(&inH);
583 
584 	Expr_getStaticReaders(a->mia_lhs, &outH);
585 	Expr_getStaticReaders(a->mia_rhs, &inH);
586 
587 	fn->fn_out = getHashKeys(&outH);
588 	fn->fn_in = getHashKeys(&inH);
589 
590 	for (i = 0;fn->fn_out[i];i++) {
591 	  if (!SHash_find(m->m_faninnodes,fn->fn_out[i]))
592 	    SHash_insert(m->m_faninnodes,fn->fn_out[i],fn);
593 	  else
594 	    errorModule(m, ModuleItem_getPlace(fn->fn_item),ERR_PATHDREASSGN,fn->fn_out[i]);
595 	}
596 
597 #if 0
598 	printf("   assign ");
599 	printHList(&outH);
600 	printf(" = ");
601 	printHList(&inH);
602 	printf("\n");
603 #endif
604 
605 
606 	SHash_uninit(&inH);
607 	SHash_uninit(&outH);
608       }
609       break;
610     case IC_GATE :
611       {
612 	MIGate *g = (MIGate*) item;
613 	FaninNode *fn = new_FaninNode(item);
614 	SHash outH,inH;
615 	ListElem *le;
616 	int i;
617 	int N = List_numElems(g->mig_ports);
618 
619 	SHash_init(&outH);
620 	SHash_init(&inH);
621 
622 	for (i = 1, le = List_first(g->mig_ports);le;i++, le = List_next(g->mig_ports,le)) {
623 	  Expr *port = (Expr*)ListElem_obj(le);
624 
625 	  if ((i == 1) || (g->mig_desc->gd_gac == GAC_MULTOUT && i != N))
626 	    Expr_getStaticReaders(port, &outH);
627 	  else
628 	    Expr_getStaticReaders(port, &inH);
629 	}
630 
631 	fn->fn_out = getHashKeys(&outH);
632 	fn->fn_in = getHashKeys(&inH);
633 
634 	for (i = 0;fn->fn_out[i];i++) {
635 	  if (!SHash_find(m->m_faninnodes,fn->fn_out[i]))
636 	    SHash_insert(m->m_faninnodes,fn->fn_out[i],fn);
637 	  else
638 	    errorModule(m, ModuleItem_getPlace(fn->fn_item),ERR_PATHDREASSGN,fn->fn_out[i]);
639 	}
640 
641 #if 0
642 	printf("   gate ");
643 	printHList(&outH);
644 	printf(" = ");
645 	printHList(&inH);
646 	printf("\n");
647 #endif
648 	SHash_uninit(&inH);
649 	SHash_uninit(&outH);
650       }
651       break;
652     }
653   }
654 
655   return 0;
656 }
657 
ModuleDecl_clearFaninFlags(ModuleDecl * m)658 void ModuleDecl_clearFaninFlags(ModuleDecl *m)
659 {
660   HashElem *he;
661   int i;
662 
663   for (he = Hash_first(m->m_faninnodes);he;he = Hash_next(m->m_faninnodes,he)) {
664     FaninNode *fn = (FaninNode *)HashElem_obj(he);
665     fn->fn_flag = 0;
666     if (fn->fn_outNets) {
667       for (i = 0;fn->fn_out[i];i++)
668 	fn->fn_outNets[i] = 0;
669     }
670     if (fn->fn_inNets) {
671       for (i = 0;fn->fn_in[i];i++)
672 	fn->fn_inNets[i] = 0;
673     }
674   }
675 }
676 
ModuleInst_findTask(ModuleInst * mi,const char * name)677 UserTask *ModuleInst_findTask(ModuleInst *mi,const char *name)
678 {
679   return Scope_findTask(ModuleInst_getScope(mi),name);
680 }
681 
ModuleInst_defineTask(ModuleInst * mi,const char * name,UserTask * ut)682 int ModuleInst_defineTask(ModuleInst *mi,const char *name,UserTask *ut)
683 {
684   return Scope_defineTask(ModuleInst_getScope(mi),name,ut);
685 }
686 
687 
688 /*****************************************************************************
689  *
690  * Create a new net declaration object
691  *
692  * Parameters:
693  *     name		Name of the net
694  *     wtype		Type of the net WIRE, REG, etc.
695  *     range		Bit-range of the net (uninstantiated)
696  *     addrRange	Address range if this is a memory (or null otherwise)
697  *     place		Place where net is declared
698  *
699  *****************************************************************************/
new_NetDecl(const char * name,int wtype,VRange * range,VRange * addrRange,Place * place)700 NetDecl *new_NetDecl(const char *name,int wtype,VRange *range,VRange *addrRange,Place *place)
701 {
702   NetDecl *n = (NetDecl *) malloc(sizeof(NetDecl));
703 
704   n->n_name = strdup(name);
705   n->n_type = wtype;
706   n->n_range = range;
707   n->n_addrRange = addrRange;
708   if (place)
709     Place_copy(&n->n_place, place);
710   else
711     Place_init(&n->n_place, "");
712 
713   return n;
714 }
715 
new_ModuleInst(ModuleDecl * md,Circuit * c,ModuleInst * parent,const char * path)716 ModuleInst *new_ModuleInst(ModuleDecl *md,Circuit *c,ModuleInst *parent,const char *path)
717 {
718   ModuleInst *mc = (ModuleInst*) malloc(sizeof(ModuleInst));
719 
720   ModuleInst_init(mc,md,c,parent,path);
721 
722   return mc;
723 }
724 
delete_ModuleInst(ModuleInst * mc)725 void delete_ModuleInst(ModuleInst *mc)
726 {
727   ModuleInst_uninit(mc);
728   free(mc);
729 }
730 
ModuleInst_init(ModuleInst * mi,ModuleDecl * md,Circuit * c,ModuleInst * parent,const char * path)731 void ModuleInst_init(ModuleInst *mi,ModuleDecl *md,Circuit *c,ModuleInst *parent,const char *path)
732 {
733   mi->mc_path = strdup(path);
734   mi->mc_peer = 0;
735   mi->mc_mod  = md;
736   mi->mc_circuit = c;
737   mi->mc_parent = parent;
738   List_init(&mi->mc_threads);
739   Scope_init(&mi->mc_scope,path,0,mi);
740 }
741 
ModuleInst_uninit(ModuleInst * mc)742 void ModuleInst_uninit(ModuleInst *mc)
743 {
744   free(mc->mc_path);
745   Scope_uninit(&mc->mc_scope);
746 }
747 
ModuleInst_findParm(ModuleInst * mc,const char * name)748 Value *ModuleInst_findParm(ModuleInst *mc,const char *name)
749 {
750   return Scope_findParm(&mc->mc_scope,name);
751 }
752 
753 
ModuleInst_defParm(ModuleInst * mc,const char * name,Value * value)754 void ModuleInst_defParm(ModuleInst *mc,const char *name,Value *value)
755 {
756   char fullName[2*STRMAX];
757   Net *n;
758 
759   sprintf(fullName,"%s.%s",mc->mc_path,name);
760   n = new_Net(fullName,NT_PARAMETER,Value_nbits(value)-1,0);
761   Value_copy(Net_getValue(n),value);
762 
763   Scope_defNet(ModuleInst_getScope(mc),name,n);
764 }
765 
766 
767 /*****************************************************************************
768  *
769  * Find a named net in the context of a module instance
770  *
771  * Parameters:
772  *     mc		Current module context
773  *     name		Name of net
774  *
775  * The following rules are used to lookup the net name:
776  *
777  *     1) Look for 'name' in the local net table.
778  *     2) If the module has a peer, look in the peer module.  For modules with
779  *        peers, this is the final search step.
780  *     3) Look for 'name' in the circuit net table for fully qualified names
781  *        such as 'top.foo.n'.
782  *     4) Treat 'name' as a relative name such as 'foo.n'.  This is done by
783  *        prepending the path for the current module and searching again as
784  *        a fully qualified path.
785  *
786  *****************************************************************************/
ModuleInst_findNet(ModuleInst * mc,const char * name)787 Net *ModuleInst_findNet(ModuleInst *mc,const char *name)
788 {
789   return Scope_findNet(ModuleInst_getScope(mc), name, 0);
790 }
791 
792 /*****************************************************************************
793  *
794  * Define a net
795  *
796  * Parameters:
797  *     mc		Current module context
798  *     name		Local name of net
799  *     n		Net object with full path name
800  *
801  *****************************************************************************/
ModuleInst_defNet(ModuleInst * mc,const char * name,Net * n)802 void ModuleInst_defNet(ModuleInst *mc,const char *name,Net *n)
803 {
804   Scope_defNet(ModuleInst_getScope(mc), name, n);
805 }
806 
807 /*****************************************************************************
808  *
809  * Lookup the local name of a net
810  *
811  * Parameters:
812  *     mi		Current module context
813  *     n		Net object
814  *
815  *****************************************************************************/
ModuleInst_findLocalNetName(ModuleInst * mi,Net * n)816 const char *ModuleInst_findLocalNetName(ModuleInst *mi,Net *n)
817 {
818   HashElem *he;
819   SHash *nets = &mi->mc_scope.s_nets;
820 
821   for (he = Hash_first(nets);he;he = Hash_next(nets,he)) {
822     Net *mi_n = (Net *) HashElem_obj(he);
823     if (mi_n == n)
824       return SHashElem_key(he);
825   }
826   return 0;
827 }
828 
new_FaninNode(ModuleItem * item)829 FaninNode *new_FaninNode(ModuleItem *item)
830 {
831   FaninNode *fn = (FaninNode*) malloc(sizeof(FaninNode));
832 
833   fn->fn_item = item;
834   fn->fn_out = 0;
835   fn->fn_outNets = 0;
836   fn->fn_in = 0;
837   fn->fn_inNets = 0;
838   fn->fn_flag = 0;
839 
840   return fn;
841 }
842 
843