1 /*
2  * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
3  * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch)
4  *
5  *    This source code is free software; you can redistribute it
6  *    and/or modify it in source code form under the terms of the GNU
7  *    General Public License as published by the Free Software
8  *    Foundation; either version 2 of the License, or (at your option)
9  *    any later version.
10  *
11  *    This program is distributed in the hope that it will be useful,
12  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *    GNU General Public License for more details.
15  *
16  *    You should have received a copy of the GNU General Public License
17  *    along with this program; if not, write to the Free Software
18  *    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 # include "config.h"
22 # include "compiler.h"
23 
24 # include  "netlist.h"
25 # include  "netclass.h"
26 # include  "netenum.h"
27 # include  "netvector.h"
28 # include  "PPackage.h"
29 # include  <cstring>
30 # include  <cstdlib>
31 # include  <sstream>
32 # include  "ivl_assert.h"
33 
34 class PExpr;
35 
Definitions()36 Definitions::Definitions()
37 {
38 }
39 
~Definitions()40 Definitions::~Definitions()
41 {
42 }
43 
add_enumeration_set(const enum_type_t * key,netenum_t * enum_set)44 void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set)
45 {
46       netenum_t*&tmp = enum_sets_[key];
47       assert(tmp == 0);
48       tmp = enum_set;
49 }
50 
add_enumeration_name(netenum_t * enum_set,perm_string name)51 bool Definitions::add_enumeration_name(netenum_t*enum_set, perm_string name)
52 {
53       netenum_t::iterator enum_val = enum_set->find_name(name);
54       assert(enum_val != enum_set->end_name());
55 
56       NetEConstEnum*val = new NetEConstEnum(this, name, enum_set, enum_val->second);
57 
58       pair<map<perm_string,NetEConstEnum*>::iterator, bool> cur;
59       cur = enum_names_.insert(make_pair(name,val));
60 
61 	// Return TRUE if the name is added (i.e. is NOT a duplicate.)
62       return cur.second;
63 }
64 
enumeration_for_key(const enum_type_t * key) const65 netenum_t* Definitions::enumeration_for_key(const enum_type_t*key) const
66 {
67       map<const enum_type_t*,netenum_t*>::const_iterator cur;
68 
69       cur = enum_sets_.find(key);
70       if (cur != enum_sets_.end())
71 	    return cur->second;
72       else
73 	    return 0;
74 }
75 
76 /*
77  * This locates the enumeration TYPE for the given enumeration literal.
78  */
enumeration_for_name(perm_string name)79 const netenum_t*Definitions::enumeration_for_name(perm_string name)
80 {
81       NetEConstEnum*tmp = enum_names_[name];
82       assert(tmp != 0);
83 
84       return tmp->enumeration();
85 }
86 
87 /*
88  * This locates the VALUE for the given enumeration literal.
89  */
enumeration_expr(perm_string key)90 const NetExpr* Definitions::enumeration_expr(perm_string key)
91 {
92       map<perm_string,NetEConstEnum*>::const_iterator eidx;
93 
94       eidx = enum_names_.find(key);
95       if (eidx != enum_names_.end()) {
96 	    return eidx->second;
97       } else {
98 	    return 0;
99       }
100 }
101 
add_class(netclass_t * net_class)102 void Definitions::add_class(netclass_t*net_class)
103 {
104       classes_[net_class->get_name()] = net_class;
105 }
106 
107 /*
108  * The NetScope class keeps a scope tree organized. Each node of the
109  * scope tree points to its parent, its right sibling and its leftmost
110  * child. The root node has no parent or siblings. The node stores the
111  * name of the scope. The complete hierarchical name of the scope is
112  * formed by appending the path of scopes from the root to the scope
113  * in question.
114  */
115 
NetScope(NetScope * up,const hname_t & n,NetScope::TYPE t,NetScope * in_unit,bool nest,bool program,bool interface,bool compilation_unit)116 NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_unit,
117 		   bool nest, bool program, bool interface, bool compilation_unit)
118 : type_(t), name_(n), nested_module_(nest), program_block_(program),
119   is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up)
120 {
121       imports_ = 0;
122       typedefs_ = 0;
123       events_ = 0;
124       lcounter_ = 0;
125       is_auto_ = false;
126       is_cell_ = false;
127       calls_stask_ = false;
128       in_final_ = false;
129 
130       if (compilation_unit)
131 	    unit_ = this;
132 
133       if (up) {
134 	    need_const_func_ = up->need_const_func_;
135 	    is_const_func_ = up->is_const_func_;
136 	    time_unit_ = up->time_unit();
137 	    time_prec_ = up->time_precision();
138 	    time_from_timescale_ = up->time_from_timescale();
139 	      // Need to check for duplicate names?
140 	    up_->children_[name_] = this;
141 	    if (unit_ == 0)
142 		  unit_ = up_->unit_;
143       } else {
144 	    need_const_func_ = false;
145 	    is_const_func_ = false;
146 	    time_unit_ = 0;
147 	    time_prec_ = 0;
148 	    time_from_timescale_ = false;
149       }
150 
151       var_init_ = 0;
152       switch (t) {
153 	  case NetScope::TASK:
154 	    task_ = 0;
155 	    break;
156 	  case NetScope::FUNC:
157 	    func_ = 0;
158 	    break;
159 	  case NetScope::MODULE:
160 	  case NetScope::PACKAGE:
161 	    module_name_ = perm_string();
162 	    break;
163 	  case NetScope::CLASS:
164 	    class_def_ = 0;
165 	    break;
166 	  default:  /* BEGIN_END and FORK_JOIN, do nothing */
167 	    break;
168       }
169       func_pform_ = 0;
170       elab_stage_ = 1;
171       lineno_ = 0;
172       def_lineno_ = 0;
173       genvar_tmp_val = 0;
174       tie_hi_ = 0;
175       tie_lo_ = 0;
176 }
177 
~NetScope()178 NetScope::~NetScope()
179 {
180       lcounter_ = 0;
181 
182 	/* name_ and module_name_ are perm-allocated. */
183 }
184 
set_line(const LineInfo * info)185 void NetScope::set_line(const LineInfo*info)
186 {
187       file_ = info->get_file();
188       def_file_ = file_;
189       lineno_ = info->get_lineno();
190       def_lineno_ = lineno_;
191 }
192 
set_line(perm_string file,unsigned lineno)193 void NetScope::set_line(perm_string file, unsigned lineno)
194 {
195       file_ = file;
196       def_file_ = file;
197       lineno_ = lineno;
198       def_lineno_ = lineno;
199 }
200 
set_line(perm_string file,perm_string def_file,unsigned lineno,unsigned def_lineno)201 void NetScope::set_line(perm_string file, perm_string def_file,
202                         unsigned lineno, unsigned def_lineno)
203 {
204       file_ = file;
205       def_file_ = def_file;
206       lineno_ = lineno;
207       def_lineno_ = def_lineno;
208 }
209 
add_imports(const map<perm_string,PPackage * > * imports)210 void NetScope::add_imports(const map<perm_string,PPackage*>*imports)
211 {
212       if (!imports->empty())
213 	    imports_ = imports;
214 }
215 
find_import(const Design * des,perm_string name)216 NetScope*NetScope::find_import(const Design*des, perm_string name)
217 {
218       if (imports_ == 0)
219 	    return 0;
220 
221       map<perm_string,PPackage*>::const_iterator cur = imports_->find(name);
222       if (cur != imports_->end()) {
223             return des->find_package(cur->second->pscope_name());
224       } else
225             return 0;
226 }
227 
add_typedefs(const map<perm_string,data_type_t * > * typedefs)228 void NetScope::add_typedefs(const map<perm_string,data_type_t*>*typedefs)
229 {
230       if (!typedefs->empty())
231 	    typedefs_ = typedefs;
232 }
233 
find_typedef_scope(const Design * des,data_type_t * type)234 NetScope*NetScope::find_typedef_scope(const Design*des, data_type_t*type)
235 {
236       assert(type);
237 
238       NetScope *cur_scope = this;
239       while (cur_scope) {
240 	    if (cur_scope->typedefs_ && cur_scope->typedefs_->find(type->name) != cur_scope->typedefs_->end())
241 		  return cur_scope;
242 	    NetScope*import_scope = cur_scope->find_import(des, type->name);
243 	    if (import_scope)
244 		  cur_scope = import_scope;
245 	    else if (cur_scope == unit_)
246 		  return 0;
247 	    else
248 		  cur_scope = cur_scope->parent();
249 
250 	    if (cur_scope == 0)
251 		  cur_scope = unit_;
252       }
253 
254       return 0;
255 }
256 
257 /*
258  * Look for the enumeration in the current scope and any parent scopes.
259  */
find_enumeration_for_name(const Design * des,perm_string name)260 const netenum_t*NetScope::find_enumeration_for_name(const Design*des, perm_string name)
261 {
262       NetScope *cur_scope = this;
263       while (cur_scope) {
264 	    NetEConstEnum*tmp = cur_scope->enum_names_[name];
265 	    if (tmp) break;
266 	    NetScope*import_scope = cur_scope->find_import(des, name);
267 	    if (import_scope)
268 		  cur_scope = import_scope;
269 	    else if (cur_scope == unit_)
270 		  return 0;
271 	    else
272 		  cur_scope = cur_scope->parent();
273 
274 	    if (cur_scope == 0)
275 		  cur_scope = unit_;
276       }
277 
278       assert(cur_scope);
279       return cur_scope->enum_names_[name]->enumeration();
280 }
281 
set_parameter(perm_string key,bool is_annotatable,PExpr * val,ivl_variable_type_t type__,PExpr * msb,PExpr * lsb,bool signed_flag,bool local_flag,NetScope::range_t * range_list,const LineInfo & file_line)282 void NetScope::set_parameter(perm_string key, bool is_annotatable,
283 			     PExpr*val, ivl_variable_type_t type__,
284 			     PExpr*msb, PExpr*lsb, bool signed_flag,
285 			     bool local_flag,
286 			     NetScope::range_t*range_list,
287 			     const LineInfo&file_line)
288 {
289       param_expr_t&ref = parameters[key];
290       ref.is_annotatable = is_annotatable;
291       ref.msb_expr = msb;
292       ref.lsb_expr = lsb;
293       ref.val_expr = val;
294       ref.val_scope = this;
295       ref.type = type__;
296       ref.msb = 0;
297       ref.lsb = 0;
298       ref.signed_flag = signed_flag;
299       ref.local_flag = local_flag;
300       ivl_assert(file_line, ref.range == 0);
301       ref.range = range_list;
302       ref.val = 0;
303       ref.set_line(file_line);
304 }
305 
306 /*
307  * This is a simplified version of set_parameter, for use when the
308  * parameter value is already known. It is currently only used to
309  * add a genvar to the parameter list.
310  */
set_parameter(perm_string key,NetExpr * val,const LineInfo & file_line)311 void NetScope::set_parameter(perm_string key, NetExpr*val,
312 			     const LineInfo&file_line)
313 {
314       param_expr_t&ref = parameters[key];
315       ref.is_annotatable = false;
316       ref.msb_expr = 0;
317       ref.lsb_expr = 0;
318       ref.val_expr = 0;
319       ref.val_scope = this;
320       ref.type = IVL_VT_BOOL;
321       ref.msb = 0;
322       ref.lsb = 0;
323       ref.signed_flag = false;
324       ref.val = val;
325       ref.set_line(file_line);
326 }
327 
auto_name(const char * prefix,char pad,const char * suffix)328 bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
329 {
330 	// Find the current reference to myself in the parent scope.
331       map<hname_t,NetScope*>::iterator self = up_->children_.find(name_);
332       assert(self != up_->children_.end());
333       assert(self->second == this);
334 
335 	// This is to keep the pad attempts from being stuck in some
336 	// sort of infinite loop. This should not be a practical
337 	// limit, but an extreme one.
338       const size_t max_pad_attempts = 32 + strlen(prefix);
339 
340       string use_prefix = prefix;
341 
342 	// Try a variety of potential new names. Make sure the new
343 	// name is not in the parent scope. Keep looking until we are
344 	// sure we have a unique name, or we run out of names to try.
345       while (use_prefix.size() <= max_pad_attempts) {
346 	      // Try this name...
347 	    string tmp = use_prefix + suffix;
348 	    hname_t new_name(lex_strings.make(tmp.c_str()), name_.peek_numbers());
349 	    if (!up_->child(new_name)) {
350 		    // Ah, this name is unique. Rename myself, and
351 		    // change my name in the parent scope.
352 		  name_ = new_name;
353 		  up_->children_.erase(self);
354 		  up_->children_[name_] = this;
355 		  return true;
356 	    }
357 
358 	      // Name collides, so try a different name.
359 	    use_prefix = use_prefix + pad;
360       }
361       return false;
362 }
363 
364 /*
365  * Return false if the parameter does not already exist.
366  * A parameter is not automatically created.
367  */
replace_parameter(perm_string key,PExpr * val,NetScope * scope)368 bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
369 {
370       if (parameters.find(key) == parameters.end())
371 	    return false;
372 
373       param_expr_t&ref = parameters[key];
374       if (ref.local_flag)
375 	    return false;
376 
377       ref.val_expr = val;
378       ref.val_scope = scope;
379       return true;
380 }
381 
make_parameter_unannotatable(perm_string key)382 bool NetScope::make_parameter_unannotatable(perm_string key)
383 {
384       bool flag = false;
385 
386       if (parameters.find(key) != parameters.end()) {
387 	    param_expr_t&ref = parameters[key];
388 	    flag = ref.is_annotatable;
389 	    ref.is_annotatable = false;
390       }
391 
392       return flag;
393 }
394 
395 /*
396  * NOTE: This method takes a const char* as a key to lookup a
397  * parameter, because we don't save that pointer. However, due to the
398  * way the map<> template works, we need to *cheat* and use the
399  * perm_string::literal method to fake the compiler into doing the
400  * compare without actually creating a perm_string.
401  */
get_parameter(Design * des,const char * key,const NetExpr * & msb,const NetExpr * & lsb)402 const NetExpr* NetScope::get_parameter(Design*des,
403 				       const char* key,
404 				       const NetExpr*&msb,
405 				       const NetExpr*&lsb)
406 {
407       return get_parameter(des, perm_string::literal(key), msb, lsb);
408 }
409 
get_parameter(Design * des,perm_string key,const NetExpr * & msb,const NetExpr * & lsb)410 const NetExpr* NetScope::get_parameter(Design*des,
411 				       perm_string key,
412 				       const NetExpr*&msb,
413 				       const NetExpr*&lsb)
414 {
415       map<perm_string,param_expr_t>::iterator idx;
416 
417       idx = parameters.find(key);
418       if (idx != parameters.end()) {
419             if (idx->second.val_expr)
420                   evaluate_parameter_(des, idx);
421 
422 	    msb = idx->second.msb;
423 	    lsb = idx->second.lsb;
424 	    return idx->second.val;
425       }
426 
427       msb = 0;
428       lsb = 0;
429       const NetExpr*tmp = enumeration_expr(key);
430       return tmp;
431 }
432 
find_parameter(perm_string key)433 NetScope::param_ref_t NetScope::find_parameter(perm_string key)
434 {
435       map<perm_string,param_expr_t>::iterator idx;
436 
437       idx = parameters.find(key);
438       if (idx != parameters.end()) return idx;
439 
440 	// To get here the parameter must already exist, so we should
441 	// never get here.
442       assert(0);
443 	// But return something to avoid a compiler warning.
444       return idx;
445 }
446 
print_type(ostream & stream) const447 void NetScope::print_type(ostream&stream) const
448 {
449       switch (type_) {
450 	case BEGIN_END:
451 	    stream << "sequential block";
452 	    break;
453 	case FORK_JOIN:
454 	    stream << "parallel block";
455 	    break;
456 	case FUNC:
457 	    stream << "function";
458 	    break;
459 	case MODULE:
460 	    stream << "module <" << module_name_ << "> instance";
461 	    break;
462 	case TASK:
463 	    stream << "task";
464 	    break;
465 	case GENBLOCK:
466 	    stream << "generate block";
467 	    break;
468 	case PACKAGE:
469 	    stream << "package " << module_name_;
470 	    break;
471 	case CLASS:
472 	    stream << "class";
473 	    break;
474       }
475 }
476 
set_task_def(NetTaskDef * def)477 void NetScope::set_task_def(NetTaskDef*def)
478 {
479       assert( type_ == TASK );
480       assert( task_ == 0 );
481       task_ = def;
482 }
483 
task_def()484 NetTaskDef* NetScope::task_def()
485 {
486       assert( type_ == TASK );
487       return task_;
488 }
489 
task_def() const490 const NetTaskDef* NetScope::task_def() const
491 {
492       assert( type_ == TASK );
493       return task_;
494 }
495 
set_func_def(NetFuncDef * def)496 void NetScope::set_func_def(NetFuncDef*def)
497 {
498       assert( type_ == FUNC );
499       assert( func_ == 0 );
500       func_ = def;
501 }
502 
func_def()503 NetFuncDef* NetScope::func_def()
504 {
505       assert( type_ == FUNC );
506       return func_;
507 }
508 
in_func() const509 bool NetScope::in_func() const
510 {
511       return (type_ == FUNC) ? true : false;
512 }
513 
func_def() const514 const NetFuncDef* NetScope::func_def() const
515 {
516       assert( type_ == FUNC );
517       return func_;
518 }
519 
set_class_def(netclass_t * def)520 void NetScope::set_class_def(netclass_t*def)
521 {
522       assert( type_ == CLASS );
523       assert( class_def_==0  );
524       class_def_ = def;
525 }
526 
class_def(void) const527 const netclass_t* NetScope::class_def(void) const
528 {
529       if (type_==CLASS)
530 	    return class_def_;
531       else
532 	    return 0;
533 }
534 
set_module_name(perm_string n)535 void NetScope::set_module_name(perm_string n)
536 {
537       assert(type_==MODULE || type_==PACKAGE);
538       module_name_ = n;
539 }
540 
module_name() const541 perm_string NetScope::module_name() const
542 {
543       assert(type_==MODULE || type_==PACKAGE);
544       return module_name_;
545 }
546 
set_num_ports(unsigned int num_ports)547 void NetScope::set_num_ports(unsigned int num_ports)
548 {
549     assert(type_ == MODULE);
550     assert(ports_.empty());
551     ports_.resize( num_ports );
552 }
553 
add_module_port_net(NetNet * subport)554 void NetScope::add_module_port_net(NetNet*subport)
555 {
556       assert(type_ == MODULE);
557       port_nets.push_back(subport);
558 }
559 
560 
add_module_port_info(unsigned idx,perm_string name,PortType::Enum ptype,unsigned long width)561 void NetScope::add_module_port_info( unsigned idx, perm_string name, PortType::Enum ptype,
562                                 unsigned long width )
563 {
564       assert(type_ == MODULE);
565       assert(ports_.size() > idx);
566       PortInfo &info = ports_[idx];
567       info.name = name;
568       info.type = ptype;
569       info.width = width;
570 }
571 
572 
module_port_nets() const573 unsigned NetScope::module_port_nets() const
574 {
575       assert(type_ == MODULE);
576       return port_nets.size();
577 }
578 
579 
module_port_info() const580 const std::vector<PortInfo> & NetScope::module_port_info() const
581 {
582       assert(type_ == MODULE);
583       return ports_;
584 }
585 
586 
587 
module_port_net(unsigned idx) const588 NetNet* NetScope::module_port_net(unsigned idx) const
589 {
590       assert(type_ == MODULE);
591       assert(idx < port_nets.size());
592       return port_nets[idx];
593 }
594 
time_unit(int val)595 void NetScope::time_unit(int val)
596 {
597       time_unit_ = val;
598 }
599 
time_precision(int val)600 void NetScope::time_precision(int val)
601 {
602       time_prec_ = val;
603 }
604 
time_from_timescale(bool val)605 void NetScope::time_from_timescale(bool val)
606 {
607       time_from_timescale_ = val;
608 }
609 
time_unit() const610 int NetScope::time_unit() const
611 {
612       return time_unit_;
613 }
614 
time_precision() const615 int NetScope::time_precision() const
616 {
617       return time_prec_;
618 }
619 
time_from_timescale() const620 bool NetScope::time_from_timescale() const
621 {
622       return time_from_timescale_;
623 }
624 
basename() const625 perm_string NetScope::basename() const
626 {
627       return name_.peek_name();
628 }
629 
add_event(NetEvent * ev)630 void NetScope::add_event(NetEvent*ev)
631 {
632       assert(ev->scope_ == 0);
633       ev->scope_ = this;
634       ev->snext_ = events_;
635       events_ = ev;
636 }
637 
rem_event(NetEvent * ev)638 void NetScope::rem_event(NetEvent*ev)
639 {
640       assert(ev->scope_ == this);
641       ev->scope_ = 0;
642       if (events_ == ev) {
643 	    events_ = ev->snext_;
644 
645       } else {
646 	    NetEvent*cur = events_;
647 	    while (cur->snext_ != ev) {
648 		  assert(cur->snext_);
649 		  cur = cur->snext_;
650 	    }
651 	    cur->snext_ = ev->snext_;
652       }
653 
654       ev->snext_ = 0;
655 }
656 
657 
find_event(perm_string name)658 NetEvent* NetScope::find_event(perm_string name)
659 {
660       for (NetEvent*cur = events_;  cur ;  cur = cur->snext_)
661 	    if (cur->name() == name)
662 		  return cur;
663 
664       return 0;
665 }
666 
add_genvar(perm_string name,LineInfo * li)667 void NetScope::add_genvar(perm_string name, LineInfo *li)
668 {
669       assert((type_ == MODULE) || (type_ == GENBLOCK));
670       genvars_[name] = li;
671 }
672 
find_genvar(perm_string name)673 LineInfo* NetScope::find_genvar(perm_string name)
674 {
675       if (genvars_.find(name) != genvars_.end())
676 	    return genvars_[name];
677       else
678             return 0;
679 }
680 
add_signal(NetNet * net)681 void NetScope::add_signal(NetNet*net)
682 {
683       signals_map_[net->name()]=net;
684 }
685 
rem_signal(NetNet * net)686 void NetScope::rem_signal(NetNet*net)
687 {
688       assert(net->scope() == this);
689       signals_map_.erase(net->name());
690 }
691 
692 /*
693  * This method looks for a signal within the current scope. The name
694  * is assumed to be the base name of the signal, so no sub-scopes are
695  * searched.
696  */
find_signal(perm_string key)697 NetNet* NetScope::find_signal(perm_string key)
698 {
699       if (signals_map_.find(key)!=signals_map_.end())
700 	    return signals_map_[key];
701       else
702 	    return 0;
703 }
704 
find_class(perm_string name)705 netclass_t*NetScope::find_class(perm_string name)
706 {
707 	// Special case: The scope itself is the class that we are
708 	// looking for. This may happen for example when elaborating
709 	// methods within the class.
710       if (type_==CLASS && name_==hname_t(name))
711 	    return class_def_;
712 
713 	// Look for the class directly within this scope.
714       map<perm_string,netclass_t*>::const_iterator cur = classes_.find(name);
715       if (cur != classes_.end())
716 	    return cur->second;
717 
718       if (up_==0 && type_==CLASS) {
719 	    assert(class_def_);
720 
721 	    NetScope*def_parent = class_def_->definition_scope();
722 	    return def_parent->find_class(name);
723       }
724 
725 	// Try looking up for the class.
726       if (up_!=0 && type_!=MODULE)
727 	    return up_->find_class(name);
728 
729 	// Try the compilation unit.
730       if (unit_ != 0)
731 	    return unit_->find_class(name);
732 
733 	// Nowhere left to try...
734       return 0;
735 }
736 
737 /*
738  * This method locates a child scope by name. The name is the simple
739  * name of the child, no hierarchy is searched.
740  */
child(const hname_t & name)741 NetScope* NetScope::child(const hname_t&name)
742 {
743       map<hname_t,NetScope*>::iterator cur = children_.find(name);
744       if (cur == children_.end())
745 	    return 0;
746       else
747 	    return cur->second;
748 }
749 
child(const hname_t & name) const750 const NetScope* NetScope::child(const hname_t&name) const
751 {
752       map<hname_t,NetScope*>::const_iterator cur = children_.find(name);
753       if (cur == children_.end())
754 	    return 0;
755       else
756 	    return cur->second;
757 }
758 
759 /* Helper function to see if the given scope is defined in a class and if
760  * so return the class scope. */
get_class_scope() const761 const NetScope* NetScope::get_class_scope() const
762 {
763       const NetScope*scope = this;
764       while (scope) {
765 	    switch(scope->type()) {
766 		case NetScope::CLASS:
767 		  return scope;
768 		case NetScope::TASK:
769 		case NetScope::FUNC:
770 		case NetScope::BEGIN_END:
771 		case NetScope::FORK_JOIN:
772 		  break;
773 		case NetScope::MODULE:
774 		case NetScope::GENBLOCK:
775 		case NetScope::PACKAGE:
776 		  return 0;
777 		default:
778 		  assert(0);
779 	    }
780 	    scope = scope->parent();
781       }
782       return scope;
783 }
784 
child_byname(perm_string name) const785 const NetScope* NetScope::child_byname(perm_string name) const
786 {
787       hname_t hname (name);
788       map<hname_t,NetScope*>::const_iterator cur = children_.lower_bound(hname);
789 
790       if (cur == children_.end())
791 	    return 0;
792 
793       if (cur->first.peek_name() == name)
794 	    return cur->second;
795 
796       return 0;
797 }
798 
799 
local_symbol()800 perm_string NetScope::local_symbol()
801 {
802       perm_string sym;
803       do {
804 	    ostringstream res;
805 	    res << "_ivl_" << (lcounter_++);
806 	    perm_string sym_tmp = lex_strings.make(res.str());
807 
808 	      // If the name already exists as a signal, try again.
809 	    if (signals_map_.find(sym_tmp) != signals_map_.end())
810 		  continue;
811 	      // If the name already exists as a parameter, try again.
812 	    if (parameters.find(sym_tmp) != parameters.end())
813 		  continue;
814 	    if (genvars_.find(sym_tmp) != genvars_.end())
815 		  continue;
816 	      // If the name already exists as a class, try again.
817 	    if (classes_.find(sym_tmp) != classes_.end())
818 		  continue;
819 
820 	      // No collisions, this is the one.
821 	    sym = sym_tmp;
822       } while (sym.nil());
823       return sym;
824 }
825 
add_tie_hi(Design * des)826 void NetScope::add_tie_hi(Design*des)
827 {
828       if (tie_hi_ == 0) {
829 	    NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC1"),
830 				    NetNet::WIRE, &netvector_t::scalar_logic);
831 	    sig->local_flag(true);
832 
833 	    tie_hi_ = new NetLogic(this, local_symbol(),
834 				   1, NetLogic::PULLUP, 1);
835 	    des->add_node(tie_hi_);
836 
837 	    connect(sig->pin(0), tie_hi_->pin(0));
838       }
839 }
840 
add_tie_lo(Design * des)841 void NetScope::add_tie_lo(Design*des)
842 {
843       if (tie_lo_ == 0) {
844 	    NetNet*sig = new NetNet(this, lex_strings.make("_LOGIC0"),
845 				    NetNet::WIRE, &netvector_t::scalar_logic);
846 	    sig->local_flag(true);
847 
848 	    tie_lo_ = new NetLogic(this, local_symbol(),
849 				   1, NetLogic::PULLDOWN, 1);
850 	    des->add_node(tie_lo_);
851 
852 	    connect(sig->pin(0), tie_lo_->pin(0));
853       }
854 }
855