1 /*
2 * Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
3 *
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20 # include "config.h"
21
22 # include <iostream>
23 # include <set>
24 # include <cstdlib>
25
26 /*
27 * This source file contains all the implementations of the Design
28 * class declared in netlist.h.
29 */
30
31 # include "netlist.h"
32 # include "util.h"
33 # include "compiler.h"
34 # include "netmisc.h"
35 # include "PExpr.h"
36 # include "PTask.h"
37 # include <sstream>
38 # include "ivl_assert.h"
39
Design()40 Design:: Design()
41 : errors(0), nodes_(0), procs_(0), aprocs_(0)
42 {
43 branches_ = 0;
44 procs_idx_ = 0;
45 des_precision_ = 0;
46 nodes_functor_cur_ = 0;
47 nodes_functor_nxt_ = 0;
48 des_delay_sel_ = Design::TYP;
49 }
50
~Design()51 Design::~Design()
52 {
53 }
54
set_precision(int val)55 void Design::set_precision(int val)
56 {
57 if (val < des_precision_)
58 des_precision_ = val;
59 }
60
get_precision() const61 int Design::get_precision() const
62 {
63 return des_precision_;
64 }
65
set_delay_sel(delay_sel_t sel)66 void Design::set_delay_sel(delay_sel_t sel)
67 {
68 des_delay_sel_ = sel;
69 }
70
get_delay_sel() const71 const char* Design::get_delay_sel() const
72 {
73 switch (des_delay_sel_) {
74 case Design::MIN:
75 return "MINIMUM";
76 break;
77 case Design::TYP:
78 return "TYPICAL";
79 break;
80 case Design::MAX:
81 return "MAXIMUM";
82 break;
83 default:
84 assert(0);
85 return "TYPICAL";
86 }
87 }
88
89
scale_to_precision(uint64_t val,const NetScope * scope) const90 uint64_t Design::scale_to_precision(uint64_t val,
91 const NetScope*scope) const
92 {
93 int units = scope->time_unit();
94 assert( units >= des_precision_ );
95
96 while (units > des_precision_) {
97 units -= 1;
98 val *= 10;
99 }
100
101 return val;
102 }
103
make_root_scope(perm_string root,NetScope * unit_scope,bool program_block,bool is_interface)104 NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope,
105 bool program_block, bool is_interface)
106 {
107 NetScope *root_scope_;
108 root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope,
109 false, program_block, is_interface);
110 /* This relies on the fact that the basename return value is
111 permallocated. */
112 root_scope_->set_module_name(root_scope_->basename());
113 root_scopes_.push_back(root_scope_);
114 return root_scope_;
115 }
116
find_root_scope()117 NetScope* Design::find_root_scope()
118 {
119 assert(root_scopes_.front());
120 return root_scopes_.front();
121 }
122
find_root_scopes() const123 list<NetScope*> Design::find_root_scopes() const
124 {
125 return root_scopes_;
126 }
127
make_package_scope(perm_string name,NetScope * unit_scope,bool is_unit)128 NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope,
129 bool is_unit)
130 {
131 NetScope*scope;
132
133 scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope,
134 false, false, false, is_unit);
135 scope->set_module_name(scope->basename());
136 packages_[name] = scope;
137 return scope;
138 }
139
find_package(perm_string name) const140 NetScope* Design::find_package(perm_string name) const
141 {
142 map<perm_string,NetScope*>::const_iterator cur = packages_.find(name);
143 if (cur == packages_.end())
144 return 0;
145
146 return cur->second;
147 }
148
find_package_scopes() const149 list<NetScope*> Design::find_package_scopes() const
150 {
151 list<NetScope*>res;
152 for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
153 ; cur != packages_.end() ; ++cur) {
154 res.push_back (cur->second);
155 }
156
157 return res;
158 }
159
160 /*
161 * This method locates a scope in the design, given its rooted
162 * hierarchical name. Each component of the key is used to scan one
163 * more step down the tree until the name runs out or the search
164 * fails.
165 */
find_scope(const std::list<hname_t> & path) const166 NetScope* Design::find_scope(const std::list<hname_t>&path) const
167 {
168 if (path.empty())
169 return 0;
170
171 for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
172 ; scope != root_scopes_.end(); ++ scope ) {
173
174 NetScope*cur = *scope;
175 if (path.front() != cur->fullname())
176 continue;
177
178 std::list<hname_t> tmp = path;
179 tmp.pop_front();
180
181 while (cur) {
182 if (tmp.empty()) return cur;
183
184 cur = cur->child( tmp.front() );
185
186 tmp.pop_front();
187 }
188 }
189
190 return 0;
191 }
192
193 /*
194 * This method locates a scope in the design, given its rooted
195 * hierarchical name. Each component of the key is used to scan one
196 * more step down the tree until the name runs out or the search
197 * fails.
198 */
find_scope(const hname_t & path) const199 NetScope* Design::find_scope(const hname_t&path) const
200 {
201 for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
202 ; scope != root_scopes_.end(); ++ scope ) {
203
204 NetScope*cur = *scope;
205 if (path.peek_name() == cur->basename())
206 return cur;
207
208 }
209
210 return 0;
211 }
212
is_design_unit(NetScope * scope)213 static bool is_design_unit(NetScope*scope)
214 {
215 return (scope->type() == NetScope::MODULE && !scope->nested_module())
216 || (scope->type() == NetScope::PACKAGE);
217 }
218
is_subroutine(NetScope::TYPE type)219 static bool is_subroutine(NetScope::TYPE type)
220 {
221 return type == NetScope::TASK || type == NetScope::FUNC;
222 }
223
224 /*
225 * This method locates a scope within another scope, given its relative
226 * hierarchical name. Each component of the key is used to scan one
227 * more step down the tree until the name runs out or the search
228 * fails.
229 */
find_scope_(NetScope * scope,const std::list<hname_t> & path,NetScope::TYPE type) const230 NetScope* Design::find_scope_(NetScope*scope, const std::list<hname_t>&path,
231 NetScope::TYPE type) const
232 {
233 std::list<hname_t> tmp = path;
234
235 do {
236 hname_t key = tmp.front();
237 /* If we are looking for a module or we are not
238 * looking at the last path component check for
239 * a name match (second line). */
240 if (scope->type() == NetScope::MODULE
241 && (type == NetScope::MODULE || tmp.size() > 1)
242 && scope->module_name()==key.peek_name()) {
243
244 /* Up references may match module name */
245
246 } else {
247 NetScope*found_scope = scope->child(key);
248 if (found_scope == 0) {
249 found_scope = scope->find_import(this, key.peek_name());
250 if (found_scope)
251 found_scope = found_scope->child(key);
252 }
253 scope = found_scope;
254 if (scope == 0) break;
255 }
256 tmp.pop_front();
257 } while (! tmp.empty());
258
259 return scope;
260 }
261
262 /*
263 * This is a relative lookup of a scope by name. The starting point is
264 * the scope parameter within which I start looking for the scope. If
265 * I do not find the scope within the passed scope, start looking in
266 * parent scopes until I find it, or I run out of parent scopes.
267 */
find_scope(NetScope * scope,const std::list<hname_t> & path,NetScope::TYPE type) const268 NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
269 NetScope::TYPE type) const
270 {
271 assert(scope);
272 if (path.empty())
273 return scope;
274
275 // Record the compilation unit scope for use later.
276 NetScope*unit_scope = scope->unit();
277
278 // First search upwards through the hierarchy.
279 while (scope) {
280 NetScope*found_scope = find_scope_(scope, path, type);
281 if (found_scope)
282 return found_scope;
283
284 // Avoid searching the unit scope twice.
285 if (scope == unit_scope)
286 unit_scope = 0;
287
288 // Special case - see IEEE 1800-2012 section 23.8.1.
289 if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
290 found_scope = find_scope_(unit_scope, path, type);
291 if (found_scope)
292 return found_scope;
293
294 unit_scope = 0;
295 }
296
297 scope = scope->parent();
298 }
299
300 // If we haven't already done so, search the compilation unit scope.
301 if (unit_scope) {
302 NetScope*found_scope = find_scope_(unit_scope, path, type);
303 if (found_scope)
304 return found_scope;
305 }
306
307 // Last chance. Look for the name starting at the root.
308 return find_scope(path);
309 }
310
311 /*
312 * This method locates a scope within another scope, given its relative
313 * hierarchical name. Each component of the key is used to scan one
314 * more step down the tree until the name runs out or the search
315 * fails.
316 */
find_scope_(NetScope * scope,const hname_t & path,NetScope::TYPE type) const317 NetScope* Design::find_scope_(NetScope*scope, const hname_t&path,
318 NetScope::TYPE type) const
319 {
320 /* If we are looking for a module or we are not
321 * looking at the last path component check for
322 * a name match (second line). */
323 if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE)
324 && (scope->module_name() == path.peek_name())) {
325 /* Up references may match module name */
326 return scope;
327 }
328 NetScope*found_scope = scope->child(path);
329 if (found_scope == 0) {
330 found_scope = scope->find_import(this, path.peek_name());
331 if (found_scope)
332 found_scope = found_scope->child(path);
333 }
334 return found_scope;
335 }
336
337 /*
338 * This is a relative lookup of a scope by name. The starting point is
339 * the scope parameter within which I start looking for the scope. If
340 * I do not find the scope within the passed scope, start looking in
341 * parent scopes until I find it, or I run out of parent scopes.
342 */
find_scope(NetScope * scope,const hname_t & path,NetScope::TYPE type) const343 NetScope* Design::find_scope(NetScope*scope, const hname_t&path,
344 NetScope::TYPE type) const
345 {
346 assert(scope);
347
348 // Record the compilation unit scope for use later.
349 NetScope*unit_scope = scope->unit();
350
351 // First search upwards through the hierarchy.
352 while (scope) {
353 NetScope*found_scope = find_scope_(scope, path, type);
354 if (found_scope)
355 return found_scope;
356
357 // Avoid searching the unit scope twice.
358 if (scope == unit_scope)
359 unit_scope = 0;
360
361 // Special case - see IEEE 1800-2012 section 23.8.1.
362 if (unit_scope && is_design_unit(scope) && is_subroutine(type)) {
363 found_scope = find_scope_(unit_scope, path, type);
364 if (found_scope)
365 return found_scope;
366
367 unit_scope = 0;
368 }
369
370 scope = scope->parent();
371 }
372
373 // If we haven't already done so, search the compilation unit scope.
374 if (unit_scope) {
375 NetScope*found_scope = find_scope_(unit_scope, path, type);
376 if (found_scope)
377 return found_scope;
378 }
379
380 // Last chance. Look for the name starting at the root.
381 list<hname_t>path_list;
382 path_list.push_back(path);
383 return find_scope(path_list);
384 }
385
386 /*
387 * This method runs through the scope, noticing the defparam
388 * statements that were collected during the elaborate_scope pass and
389 * applying them to the target parameters. The implementation actually
390 * works by using a specialized method from the NetScope class that
391 * does all the work for me.
392 */
run_defparams()393 void Design::run_defparams()
394 {
395 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
396 scope != root_scopes_.end(); ++ scope )
397 (*scope)->run_defparams(this);
398 }
399
run_defparams(Design * des)400 void NetScope::run_defparams(Design*des)
401 {
402 for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
403 ; cur != children_.end() ; ++ cur )
404 cur->second->run_defparams(des);
405
406 while (! defparams.empty()) {
407 pair<pform_name_t,PExpr*> pp = defparams.front();
408 defparams.pop_front();
409
410 pform_name_t path = pp.first;
411 PExpr*val = pp.second;
412
413 perm_string perm_name = peek_tail_name(path);
414 path.pop_back();
415
416 list<hname_t> eval_path = eval_scope_path(des, this, path);
417
418 /* If there is no path on the name, then the targ_scope
419 is the current scope. */
420 NetScope*targ_scope = des->find_scope(this, eval_path);
421 if (targ_scope == 0) {
422
423 // Push the defparam onto a list for retry
424 // later. It is possible for the scope lookup to
425 // fail if the scope being defparam'd into is
426 // generated by an index array for generate.
427 eval_path.push_back(hname_t(perm_name));
428 defparams_later.push_back(make_pair(eval_path,val));
429 continue;
430 }
431
432 bool flag = targ_scope->replace_parameter(perm_name, val, this);
433 if (! flag) {
434 cerr << val->get_fileline() << ": warning: parameter "
435 << perm_name << " not found in "
436 << scope_path(targ_scope) << "." << endl;
437 }
438
439 }
440
441 // If some of the defparams didn't find a scope in the name,
442 // then try again later. It may be that the target scope is
443 // created later by generate scheme or instance array.
444 if (! defparams_later.empty())
445 des->defparams_later.insert(this);
446 }
447
run_defparams_later(Design * des)448 void NetScope::run_defparams_later(Design*des)
449 {
450 set<NetScope*> target_scopes;
451 list<pair<list<hname_t>,PExpr*> > defparams_even_later;
452
453 while (! defparams_later.empty()) {
454 pair<list<hname_t>,PExpr*> cur = defparams_later.front();
455 defparams_later.pop_front();
456
457 list<hname_t>eval_path = cur.first;
458 perm_string name = eval_path.back().peek_name();
459 eval_path.pop_back();
460
461 PExpr*val = cur.second;
462
463 NetScope*targ_scope = des->find_scope(this, eval_path);
464 if (targ_scope == 0) {
465 // If a scope in the target path is not found,
466 // then push this defparam for handling even
467 // later. Maybe a later generate scheme or
468 // instance array will create the scope.
469 defparams_even_later.push_back(cur);
470 continue;
471 }
472
473 bool flag = targ_scope->replace_parameter(name, val, this);
474 if (! flag) {
475 cerr << val->get_fileline() << ": warning: parameter "
476 << name << " not found in "
477 << scope_path(targ_scope) << "." << endl;
478 }
479
480 // We'll need to re-evaluate parameters in this scope
481 target_scopes.insert(targ_scope);
482 }
483
484 // The scopes that this defparam set touched will be
485 // re-evaluated later it a top_defparams work item. So do not
486 // do the evaluation now.
487
488 // If there are some scopes that still have missing scopes,
489 // then save them back into the defparams_later list for a
490 // later pass.
491 defparams_later = defparams_even_later;
492 if (! defparams_later.empty())
493 des->defparams_later.insert(this);
494 }
495
evaluate_parameters()496 void Design::evaluate_parameters()
497 {
498 for (map<perm_string,NetScope*>::const_iterator cur = packages_.begin()
499 ; cur != packages_.end() ; ++ cur) {
500 cur->second->evaluate_parameters(this);
501 }
502
503 for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
504 ; scope != root_scopes_.end() ; ++ scope ) {
505 (*scope)->evaluate_parameters(this);
506 }
507 }
508
evaluate_parameter_logic_(Design * des,param_ref_t cur)509 void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
510 {
511 long msb = 0;
512 long lsb = 0;
513 bool range_flag = false;
514
515 /* Evaluate the msb expression, if it is present. */
516 PExpr*msb_expr = (*cur).second.msb_expr;
517 if (msb_expr) {
518 (*cur).second.msb = elab_and_eval(des, this, msb_expr, -1, true);
519 if (! eval_as_long(msb, (*cur).second.msb)) {
520 cerr << (*cur).second.val->get_fileline()
521 << ": error: Unable to evaluate msb expression "
522 << "for parameter " << (*cur).first << ": "
523 << *(*cur).second.msb << endl;
524 des->errors += 1;
525 return;
526 }
527
528 range_flag = true;
529 }
530
531 /* Evaluate the lsb expression, if it is present. */
532 PExpr*lsb_expr = (*cur).second.lsb_expr;
533 if (lsb_expr) {
534 (*cur).second.lsb = elab_and_eval(des, this, lsb_expr, -1, true);
535 if (! eval_as_long(lsb, (*cur).second.lsb)) {
536 cerr << (*cur).second.val->get_fileline()
537 << ": error: Unable to evaluate lsb expression "
538 << "for parameter " << (*cur).first << ": "
539 << *(*cur).second.lsb << endl;
540 des->errors += 1;
541 return;
542 }
543
544 range_flag = true;
545 }
546
547 /* Evaluate the parameter expression. */
548 PExpr*val_expr = (*cur).second.val_expr;
549 NetScope*val_scope = (*cur).second.val_scope;
550
551 int lv_width = -2;
552 if (range_flag)
553 lv_width = (msb >= lsb) ? 1 + msb - lsb : 1 + lsb - msb;
554
555 NetExpr*expr = elab_and_eval(des, val_scope, val_expr, lv_width, true,
556 (*cur).second.is_annotatable,
557 (*cur).second.type);
558 if (! expr)
559 return;
560
561 switch (expr->expr_type()) {
562 case IVL_VT_REAL:
563 if (! dynamic_cast<const NetECReal*>(expr)) {
564 cerr << expr->get_fileline()
565 << ": error: Unable to evaluate real parameter "
566 << (*cur).first << " value: " << *expr << endl;
567 des->errors += 1;
568 return;
569 }
570 break;
571
572 case IVL_VT_LOGIC:
573 case IVL_VT_BOOL:
574 if (! dynamic_cast<const NetEConst*>(expr)) {
575 cerr << expr->get_fileline()
576 << ": error: Unable to evaluate parameter "
577 << (*cur).first << " value: " << *expr << endl;
578 des->errors += 1;
579 return;
580 }
581
582 // If the parameter has type or range information, then
583 // make sure the type is set right. Note that if the
584 // parameter doesn't have an explicit type or range,
585 // then it will get the signedness from the expression itself.
586 if (cur->second.type != IVL_VT_NO_TYPE) {
587 expr->cast_signed(cur->second.signed_flag);
588 } else if (cur->second.signed_flag) {
589 expr->cast_signed(true);
590 }
591
592 if (!range_flag && !expr->has_width()) {
593 expr = pad_to_width(expr, integer_width, *expr);
594 }
595 break;
596
597 default:
598 cerr << expr->get_fileline()
599 << ": internal error: "
600 << "Unhandled expression type?" << endl;
601 des->errors += 1;
602 return;
603 }
604
605 cur->second.val = expr;
606
607 // If there are no value ranges to test the value against,
608 // then we are done.
609 if ((*cur).second.range == 0) {
610 return;
611 }
612
613 NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.val);
614 ivl_assert(*(*cur).second.val, (*cur).second.val);
615 ivl_assert(*(*cur).second.val, val);
616
617 verinum value = val->value();
618
619 bool from_flag = (*cur).second.range == 0? true : false;
620 for (range_t*value_range = (*cur).second.range
621 ; value_range ; value_range = value_range->next) {
622
623 // If we already know that the value is
624 // within a "from" range, then do not test
625 // any more of the from ranges.
626 if (from_flag && value_range->exclude_flag==false)
627 continue;
628
629 if (value_range->low_expr) {
630 NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->low_expr);
631 ivl_assert(*value_range->low_expr, tmp);
632 if (value_range->low_open_flag && value <= tmp->value())
633 continue;
634 else if (value < tmp->value())
635 continue;
636 }
637
638 if (value_range->high_expr) {
639 NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->high_expr);
640 ivl_assert(*value_range->high_expr, tmp);
641 if (value_range->high_open_flag && value >= tmp->value())
642 continue;
643 else if (value > tmp->value())
644 continue;
645 }
646
647 // Within the range. If this is a "from"
648 // range, then set the from_flag and continue.
649 if (value_range->exclude_flag == false) {
650 from_flag = true;
651 continue;
652 }
653
654 // OH NO! In an excluded range. signal an error.
655 from_flag = false;
656 break;
657 }
658
659 // If we found no from range that contains the
660 // value, then report an error.
661 if (! from_flag) {
662 cerr << val->get_fileline() << ": error: "
663 << "Parameter value " << value
664 << " is out of range for parameter " << (*cur).first
665 << "." << endl;
666 des->errors += 1;
667 }
668 }
669
evaluate_parameter_real_(Design * des,param_ref_t cur)670 void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
671 {
672 PExpr*val_expr = (*cur).second.val_expr;
673 NetScope*val_scope = (*cur).second.val_scope;
674
675 NetExpr*expr = elab_and_eval(des, val_scope, val_expr, -1, true,
676 (*cur).second.is_annotatable,
677 (*cur).second.type);
678 if (! expr)
679 return;
680
681 NetECReal*res = 0;
682
683 switch (expr->expr_type()) {
684 case IVL_VT_REAL:
685 if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
686 res = tmp;
687 } else {
688 cerr << expr->get_fileline()
689 << ": error: "
690 << "Unable to evaluate real parameter "
691 << (*cur).first << " value: " << *expr << endl;
692 des->errors += 1;
693 return;
694 }
695 break;
696
697 default:
698 cerr << expr->get_fileline()
699 << ": internal error: "
700 << "Failed to cast expression?" << endl;
701 des->errors += 1;
702 return;
703 break;
704 }
705
706 (*cur).second.val = res;
707 double value = res->value().as_double();
708
709 bool from_flag = (*cur).second.range == 0? true : false;
710 for (range_t*value_range = (*cur).second.range
711 ; value_range ; value_range = value_range->next) {
712
713 if (from_flag && value_range->exclude_flag==false)
714 continue;
715
716 if (value_range->low_expr) {
717 double tmp;
718 bool flag = eval_as_double(tmp, value_range->low_expr);
719 ivl_assert(*value_range->low_expr, flag);
720 if (value_range->low_open_flag && value <= tmp)
721 continue;
722 else if (value < tmp)
723 continue;
724 }
725
726 if (value_range->high_expr) {
727 double tmp;
728 bool flag = eval_as_double(tmp, value_range->high_expr);
729 ivl_assert(*value_range->high_expr, flag);
730 if (value_range->high_open_flag && value >= tmp)
731 continue;
732 else if (value > tmp)
733 continue;
734 }
735
736 if (value_range->exclude_flag == false) {
737 from_flag = true;
738 continue;
739 }
740
741 // All the above tests failed, so we must have tripped
742 // an exclude rule.
743 from_flag = false;
744 break;
745 }
746
747 if (! from_flag) {
748 cerr << res->get_fileline() << ": error: "
749 << "Parameter value " << value
750 << " is out of range for real parameter " << (*cur).first
751 << "." << endl;
752 des->errors += 1;
753 }
754 }
755
evaluate_parameter_(Design * des,param_ref_t cur)756 void NetScope::evaluate_parameter_(Design*des, param_ref_t cur)
757 {
758 // If the parameter has already been evaluated, quietly return.
759 if (cur->second.val_expr == 0)
760 return;
761
762 if (cur->second.solving) {
763 cerr << cur->second.get_fileline() << ": error: "
764 << "Recursive parameter reference found involving "
765 << cur->first << "." << endl;
766 des->errors += 1;
767 } else {
768 cur->second.solving = true;
769 switch (cur->second.type) {
770 case IVL_VT_NO_TYPE:
771 case IVL_VT_BOOL:
772 case IVL_VT_LOGIC:
773 evaluate_parameter_logic_(des, cur);
774 break;
775
776 case IVL_VT_REAL:
777 evaluate_parameter_real_(des, cur);
778 break;
779
780 default:
781 cerr << cur->second.get_fileline() << ": internal error: "
782 << "Unexpected expression type " << cur->second.type
783 << "." << endl;
784 cerr << cur->second.get_fileline() << ": : "
785 << "Parameter name: " << cur->first << endl;
786 cerr << cur->second.get_fileline() << ": : "
787 << "Expression is: " << *cur->second.val_expr << endl;
788 ivl_assert(cur->second, 0);
789 break;
790 }
791 cur->second.solving = false;
792 }
793
794 // If we have failed to evaluate the expression, create a dummy
795 // value. This prevents spurious error messages being output.
796 if (cur->second.val == 0) {
797 verinum val(verinum::Vx);
798 cur->second.val = new NetEConst(val);
799 }
800
801 // Flag that the expression has been evaluated.
802 cur->second.val_expr = 0;
803 }
804
evaluate_parameters(Design * des)805 void NetScope::evaluate_parameters(Design*des)
806 {
807 for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
808 ; cur != children_.end() ; ++ cur )
809 cur->second->evaluate_parameters(des);
810
811 if (debug_scopes)
812 cerr << "debug: "
813 << "Evaluating parameters in " << scope_path(this) << endl;
814
815 for (param_ref_t cur = parameters.begin()
816 ; cur != parameters.end() ; ++ cur) {
817
818 evaluate_parameter_(des, cur);
819 }
820 }
821
residual_defparams()822 void Design::residual_defparams()
823 {
824 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
825 scope != root_scopes_.end(); ++ scope )
826 (*scope)->residual_defparams(this);
827 }
828
residual_defparams(Design * des)829 void NetScope::residual_defparams(Design*des)
830 {
831 // Clean out the list of defparams that never managed to match
832 // a scope. Print a warning for each.
833 while (! defparams_later.empty()) {
834 pair<list<hname_t>,PExpr*> cur = defparams_later.front();
835 defparams_later.pop_front();
836
837 cerr << cur.second->get_fileline() << ": warning: "
838 << "Scope of " << cur.first << " not found." << endl;
839 }
840
841 for (map<hname_t,NetScope*>::const_iterator cur = children_.begin()
842 ; cur != children_.end() ; ++ cur )
843 cur->second->residual_defparams(des);
844 }
845
get_flag(const string & key) const846 const char* Design::get_flag(const string&key) const
847 {
848 map<string,const char*>::const_iterator tmp = flags_.find(key);
849 if (tmp == flags_.end())
850 return "";
851 else
852 return (*tmp).second;
853 }
854
855 /*
856 * This method looks for a signal (reg, wire, whatever) starting at
857 * the specified scope. If the name is hierarchical, it is split into
858 * scope and name and the scope used to find the proper starting point
859 * for the real search.
860 *
861 * It is the job of this function to properly implement Verilog scope
862 * rules as signals are concerned.
863 */
find_signal(NetScope * scope,pform_name_t path)864 NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
865 {
866 assert(scope);
867
868 perm_string key = peek_tail_name(path);
869 path.pop_back();
870 if (! path.empty()) {
871 list<hname_t> eval_path = eval_scope_path(this, scope, path);
872 scope = find_scope(scope, eval_path);
873 }
874
875 while (scope) {
876 if (NetNet*net = scope->find_signal(key))
877 return net;
878
879 if (NetScope*import_scope = scope->find_import(this, key)) {
880 scope = import_scope;
881 continue;
882 }
883
884 if (scope->type() == NetScope::MODULE)
885 break;
886
887 scope = scope->parent();
888 }
889
890 return 0;
891 }
892
find_function(NetScope * scope,const pform_name_t & name)893 NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
894 {
895 assert(scope);
896
897 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
898 NetScope*func = find_scope(scope, eval_path, NetScope::FUNC);
899 if (func && (func->type() == NetScope::FUNC)) {
900 // If a function is used in a parameter definition or in
901 // a signal declaration, it is possible to get here before
902 // the function's signals have been elaborated. If this is
903 // the case, elaborate them now.
904 if (func->elab_stage() < 2) {
905 func->need_const_func(true);
906 const PFunction*pfunc = func->func_pform();
907 assert(pfunc);
908 pfunc->elaborate_sig(this, func);
909 }
910 return func->func_def();
911 }
912 return 0;
913 }
914
find_task(NetScope * scope,const pform_name_t & name)915 NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
916 {
917 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
918 NetScope*task = find_scope(scope, eval_path, NetScope::TASK);
919 if (task && (task->type() == NetScope::TASK))
920 return task;
921
922 return 0;
923 }
924
add_node(NetNode * net)925 void Design::add_node(NetNode*net)
926 {
927 assert(net->design_ == 0);
928 if (nodes_ == 0) {
929 net->node_next_ = net;
930 net->node_prev_ = net;
931 } else {
932 net->node_next_ = nodes_->node_next_;
933 net->node_prev_ = nodes_;
934 net->node_next_->node_prev_ = net;
935 net->node_prev_->node_next_ = net;
936 }
937 nodes_ = net;
938 net->design_ = this;
939 }
940
del_node(NetNode * net)941 void Design::del_node(NetNode*net)
942 {
943 assert(net != 0);
944 assert(net->design_ == this);
945
946 /* Interact with the Design::functor method by manipulating the
947 cur and nxt pointers that it is using. */
948 if (net == nodes_functor_nxt_)
949 nodes_functor_nxt_ = nodes_functor_nxt_->node_next_;
950 if (net == nodes_functor_nxt_)
951 nodes_functor_nxt_ = 0;
952
953 if (net == nodes_functor_cur_)
954 nodes_functor_cur_ = 0;
955
956 /* Now perform the actual delete. */
957 if (nodes_ == net)
958 nodes_ = net->node_prev_;
959
960 if (nodes_ == net) {
961 nodes_ = 0;
962 } else {
963 net->node_next_->node_prev_ = net->node_prev_;
964 net->node_prev_->node_next_ = net->node_next_;
965 }
966
967 net->design_ = 0;
968 }
969
add_branch(NetBranch * bra)970 void Design::add_branch(NetBranch*bra)
971 {
972 bra->next_ = branches_;
973 branches_ = bra;
974 }
975
add_process(NetProcTop * pro)976 void Design::add_process(NetProcTop*pro)
977 {
978 pro->next_ = procs_;
979 procs_ = pro;
980 }
981
add_process(NetAnalogTop * pro)982 void Design::add_process(NetAnalogTop*pro)
983 {
984 pro->next_ = aprocs_;
985 aprocs_ = pro;
986 }
delete_process(NetProcTop * top)987 void Design::delete_process(NetProcTop*top)
988 {
989 assert(top);
990 if (procs_ == top) {
991 procs_ = top->next_;
992
993 } else {
994 NetProcTop*cur = procs_;
995 while (cur->next_ != top) {
996 assert(cur->next_);
997 cur = cur->next_;
998 }
999
1000 cur->next_ = top->next_;
1001 }
1002
1003 if (procs_idx_ == top)
1004 procs_idx_ = top->next_;
1005
1006 delete top;
1007 }
1008
join_islands(void)1009 void Design::join_islands(void)
1010 {
1011 if (nodes_ == 0)
1012 return;
1013
1014 NetNode*cur = nodes_->node_next_;
1015 do {
1016 join_island(cur);
1017 cur = cur->node_next_;
1018 } while (cur != nodes_->node_next_);
1019 }
1020