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