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