Fix for pr1833776.
[iverilog.git] / net_design.cc
blob0044c8e787e9a645fd57f2939bb6f0f0c3d216a8
1 /*
2 * Copyright (c) 2000-2003 Stephen Williams (steve@icarus.com)
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
28 * This source file contains all the implementations of the Design
29 * class declared in netlist.h.
32 # include "netlist.h"
33 # include "util.h"
34 # include "compiler.h"
35 # include "netmisc.h"
36 # include <sstream>
38 Design:: Design()
39 : errors(0), nodes_(0), procs_(0), lcounter_(0)
41 procs_idx_ = 0;
42 des_precision_ = 0;
43 nodes_functor_cur_ = 0;
44 nodes_functor_nxt_ = 0;
47 Design::~Design()
51 string Design::local_symbol(const string&path)
53 ostringstream res;
54 res << path << "." << "_L" << lcounter_;
55 lcounter_ += 1;
57 return res.str();
60 void Design::set_precision(int val)
62 if (val < des_precision_)
63 des_precision_ = val;
66 int Design::get_precision() const
68 return des_precision_;
71 uint64_t Design::scale_to_precision(uint64_t val,
72 const NetScope*scope) const
74 int units = scope->time_unit();
75 assert( units >= des_precision_ );
77 while (units > des_precision_) {
78 units -= 1;
79 val *= 10;
82 return val;
85 NetScope* Design::make_root_scope(perm_string root)
87 NetScope *root_scope_;
88 root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
89 /* This relies on the fact that the basename return value is
90 permallocated. */
91 root_scope_->set_module_name(root_scope_->basename());
92 root_scopes_.push_back(root_scope_);
93 return root_scope_;
96 NetScope* Design::find_root_scope()
98 assert(root_scopes_.front());
99 return root_scopes_.front();
102 list<NetScope*> Design::find_root_scopes()
104 return root_scopes_;
107 const list<NetScope*> Design::find_root_scopes() const
109 return root_scopes_;
113 * This method locates a scope in the design, given its rooted
114 * hierarchical name. Each component of the key is used to scan one
115 * more step down the tree until the name runs out or the search
116 * fails.
118 NetScope* Design::find_scope(const std::list<hname_t>&path) const
120 if (path.empty())
121 return 0;
123 for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
124 ; scope != root_scopes_.end(); scope++) {
126 NetScope*cur = *scope;
127 if (path.front() != cur->fullname())
128 continue;
130 std::list<hname_t> tmp = path;
131 tmp.pop_front();
133 while (cur) {
134 if (tmp.empty()) return cur;
136 cur = cur->child( tmp.front() );
138 tmp.pop_front();
143 return 0;
147 * This is a relative lookup of a scope by name. The starting point is
148 * the scope parameter within which I start looking for the scope. If
149 * I do not find the scope within the passed scope, start looking in
150 * parent scopes until I find it, or I run out of parent scopes.
152 NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) const
154 assert(scope);
155 if (path.empty())
156 return scope;
158 for ( ; scope ; scope = scope->parent()) {
160 std::list<hname_t> tmp = path;
162 NetScope*cur = scope;
163 do {
164 hname_t key = tmp.front();
165 if (cur->type() == NetScope::MODULE
166 && cur->module_name()==key.peek_name()) {
168 /* Up references may match module name */
170 } else {
171 cur = cur->child( key );
172 if (cur == 0) break;
174 tmp.pop_front();
175 } while (!tmp.empty());
177 if (cur) return cur;
180 // Last chance. Look for the name starting at the root.
181 return find_scope(path);
185 * This method runs through the scope, noticing the defparam
186 * statements that were collected during the elaborate_scope pass and
187 * applying them to the target parameters. The implementation actually
188 * works by using a specialized method from the NetScope class that
189 * does all the work for me.
191 void Design::run_defparams()
193 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
194 scope != root_scopes_.end(); scope++)
195 (*scope)->run_defparams(this);
198 void NetScope::run_defparams(Design*des)
200 { NetScope*cur = sub_;
201 while (cur) {
202 cur->run_defparams(des);
203 cur = cur->sib_;
207 map<pform_name_t,NetExpr*>::const_iterator pp;
208 for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
209 NetExpr*val = (*pp).second;
210 pform_name_t path = (*pp).first;
212 perm_string perm_name = peek_tail_name(path);
213 path.pop_back();
215 list<hname_t> eval_path = eval_scope_path(des, this, path);
217 /* If there is no path on the name, then the targ_scope
218 is the current scope. */
219 NetScope*targ_scope = des->find_scope(this, eval_path);
220 if (targ_scope == 0) {
221 cerr << val->get_line() << ": warning: scope of " <<
222 path << "." << perm_name << " not found." << endl;
223 continue;
226 bool flag = targ_scope->replace_parameter(perm_name, val);
227 if (! flag) {
228 cerr << val->get_line() << ": warning: parameter "
229 << perm_name << " not found in "
230 << scope_path(targ_scope) << "." << endl;
236 void Design::evaluate_parameters()
238 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
239 scope != root_scopes_.end(); scope++)
240 (*scope)->evaluate_parameters(this);
243 void NetScope::evaluate_parameters(Design*des)
245 NetScope*cur = sub_;
246 while (cur) {
247 cur->evaluate_parameters(des);
248 cur = cur->sib_;
252 // Evaluate the parameter values. The parameter expressions
253 // have already been elaborated and replaced by the scope
254 // scanning code. Now the parameter expression can be fully
255 // evaluated, or it cannot be evaluated at all.
257 typedef map<perm_string,param_expr_t>::iterator mparm_it_t;
259 for (mparm_it_t cur = parameters.begin()
260 ; cur != parameters.end() ; cur ++) {
262 long msb = 0;
263 long lsb = 0;
264 bool range_flag = false;
265 NetExpr*expr;
267 /* Evaluate the msb expression, if it is present. */
268 expr = (*cur).second.msb;
270 if (expr) {
272 NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
274 if (! tmp) {
276 NetExpr*nexpr = expr->eval_tree();
277 if (nexpr == 0) {
278 cerr << (*cur).second.expr->get_line()
279 << ": internal error: "
280 << "unable to evaluate msb expression "
281 << "for parameter " << (*cur).first << ": "
282 << *expr << endl;
283 des->errors += 1;
284 continue;
287 assert(nexpr);
288 delete expr;
289 (*cur).second.msb = nexpr;
291 tmp = dynamic_cast<NetEConst*>(nexpr);
294 assert(tmp);
295 msb = tmp->value().as_long();
296 range_flag = true;
299 /* Evaluate the lsb expression, if it is present. */
300 expr = (*cur).second.lsb;
301 if (expr) {
303 NetEConst*tmp = dynamic_cast<NetEConst*>(expr);
305 if (! tmp) {
307 NetExpr*nexpr = expr->eval_tree();
308 if (nexpr == 0) {
309 cerr << (*cur).second.expr->get_line()
310 << ": internal error: "
311 << "unable to evaluate lsb expression "
312 << "for parameter " << (*cur).first << ": "
313 << *expr << endl;
314 des->errors += 1;
315 continue;
318 assert(nexpr);
319 delete expr;
320 (*cur).second.lsb = nexpr;
322 tmp = dynamic_cast<NetEConst*>(nexpr);
325 assert(tmp);
326 lsb = tmp->value().as_long();
328 assert(range_flag);
332 /* Evaluate the parameter expression, if necessary. */
333 expr = (*cur).second.expr;
334 assert(expr);
336 switch (expr->expr_type()) {
337 case IVL_VT_REAL:
338 if (! dynamic_cast<const NetECReal*>(expr)) {
340 NetExpr*nexpr = expr->eval_tree();
341 if (nexpr == 0) {
342 cerr << (*cur).second.expr->get_line()
343 << ": internal error: "
344 << "unable to evaluate real parameter value: "
345 << *expr << endl;
346 des->errors += 1;
347 continue;
350 assert(nexpr);
351 delete expr;
352 (*cur).second.expr = nexpr;
354 break;
356 case IVL_VT_LOGIC:
357 case IVL_VT_BOOL:
358 if (! dynamic_cast<const NetEConst*>(expr)) {
360 // Try to evaluate the expression.
361 NetExpr*nexpr = expr->eval_tree();
362 if (nexpr == 0) {
363 cerr << (*cur).second.expr->get_line()
364 << ": internal error: "
365 << "unable to evaluate parameter "
366 << (*cur).first
367 << " value: " <<
368 *expr << endl;
369 des->errors += 1;
370 continue;
373 // The evaluate worked, replace the old
374 // expression with this constant value.
375 assert(nexpr);
376 delete expr;
377 (*cur).second.expr = nexpr;
379 // Set the signedness flag.
380 (*cur).second.expr
381 ->cast_signed( (*cur).second.signed_flag );
383 break;
385 default:
386 cerr << (*cur).second.expr->get_line()
387 << ": internal error: "
388 << "unhandled expression type?" << endl;
389 des->errors += 1;
390 continue;
393 /* If the parameter has range information, then make
394 sure the value is set right. */
395 if (range_flag) {
396 unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
397 wid += 1;
399 NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
400 assert(val);
402 verinum value = val->value();
404 if (! (value.has_len()
405 && (value.len() == wid)
406 && (value.has_sign() == (*cur).second.signed_flag))) {
408 verinum tmp (value, wid);
409 tmp.has_sign ( (*cur).second.signed_flag );
410 delete val;
411 val = new NetEConst(tmp);
412 (*cur).second.expr = val;
419 const char* Design::get_flag(const string&key) const
421 map<string,const char*>::const_iterator tmp = flags_.find(key);
422 if (tmp == flags_.end())
423 return "";
424 else
425 return (*tmp).second;
429 * This method looks for a signal (reg, wire, whatever) starting at
430 * the specified scope. If the name is hierarchical, it is split into
431 * scope and name and the scope used to find the proper starting point
432 * for the real search.
434 * It is the job of this function to properly implement Verilog scope
435 * rules as signals are concerned.
437 NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
439 assert(scope);
441 perm_string key = peek_tail_name(path);
442 path.pop_back();
443 if (! path.empty()) {
444 list<hname_t> eval_path = eval_scope_path(this, scope, path);
445 scope = find_scope(scope, eval_path);
448 while (scope) {
449 if (NetNet*net = scope->find_signal(key))
450 return net;
452 if (scope->type() == NetScope::MODULE)
453 break;
455 scope = scope->parent();
458 return 0;
461 NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
463 assert(scope);
465 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
466 NetScope*func = find_scope(scope, eval_path);
467 if (func && (func->type() == NetScope::FUNC))
468 return func->func_def();
470 return 0;
473 NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
475 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
476 NetScope*task = find_scope(scope, eval_path);
477 if (task && (task->type() == NetScope::TASK))
478 return task;
480 return 0;
483 void Design::add_node(NetNode*net)
485 assert(net->design_ == 0);
486 if (nodes_ == 0) {
487 net->node_next_ = net;
488 net->node_prev_ = net;
489 } else {
490 net->node_next_ = nodes_->node_next_;
491 net->node_prev_ = nodes_;
492 net->node_next_->node_prev_ = net;
493 net->node_prev_->node_next_ = net;
495 nodes_ = net;
496 net->design_ = this;
499 void Design::del_node(NetNode*net)
501 assert(net->design_ == this);
502 assert(net != 0);
504 /* Interact with the Design::functor method by manipulating the
505 cur and nxt pointers that it is using. */
506 if (net == nodes_functor_nxt_)
507 nodes_functor_nxt_ = nodes_functor_nxt_->node_next_;
508 if (net == nodes_functor_nxt_)
509 nodes_functor_nxt_ = 0;
511 if (net == nodes_functor_cur_)
512 nodes_functor_cur_ = 0;
514 /* Now perform the actual delete. */
515 if (nodes_ == net)
516 nodes_ = net->node_prev_;
518 if (nodes_ == net) {
519 nodes_ = 0;
520 } else {
521 net->node_next_->node_prev_ = net->node_prev_;
522 net->node_prev_->node_next_ = net->node_next_;
525 net->design_ = 0;
528 void Design::add_process(NetProcTop*pro)
530 pro->next_ = procs_;
531 procs_ = pro;
534 void Design::delete_process(NetProcTop*top)
536 assert(top);
537 if (procs_ == top) {
538 procs_ = top->next_;
540 } else {
541 NetProcTop*cur = procs_;
542 while (cur->next_ != top) {
543 assert(cur->next_);
544 cur = cur->next_;
547 cur->next_ = top->next_;
550 if (procs_idx_ == top)
551 procs_idx_ = top->next_;
553 delete top;
557 * $Log: net_design.cc,v $
558 * Revision 1.54 2007/06/05 04:18:09 steve
559 * Upward names may reference modules by module_name.
561 * Revision 1.53 2007/06/02 03:42:13 steve
562 * Properly evaluate scope path expressions.
564 * Revision 1.52 2007/05/24 04:07:12 steve
565 * Rework the heirarchical identifier parse syntax and pform
566 * to handle more general combinations of heirarch and bit selects.
568 * Revision 1.51 2007/04/26 03:06:22 steve
569 * Rework hname_t to use perm_strings.
571 * Revision 1.50 2006/08/08 05:11:37 steve
572 * Handle 64bit delay constants.
574 * Revision 1.49 2006/07/31 03:50:17 steve
575 * Add support for power in constant expressions.
577 * Revision 1.48 2005/11/27 05:56:20 steve
578 * Handle bit select of parameter with ranges.
580 * Revision 1.47 2005/09/14 02:53:14 steve
581 * Support bool expressions and compares handle them optimally.
583 * Revision 1.46 2005/07/11 16:56:50 steve
584 * Remove NetVariable and ivl_variable_t structures.
586 * Revision 1.45 2004/10/04 01:10:54 steve
587 * Clean up spurious trailing white space.
589 * Revision 1.44 2004/02/20 06:22:56 steve
590 * parameter keys are per_strings.
592 * Revision 1.43 2004/02/18 17:11:56 steve
593 * Use perm_strings for named langiage items.
595 * Revision 1.42 2003/11/10 20:59:03 steve
596 * Design::get_flag returns const char* instead of string.
598 * Revision 1.41 2003/09/20 01:05:36 steve
599 * Obsolete find_symbol and find_event from the Design class.
601 * Revision 1.40 2003/09/19 03:50:12 steve
602 * Remove find_memory method from Design class.
604 * Revision 1.39 2003/09/19 03:30:05 steve
605 * Fix name search in elab_lval.
607 * Revision 1.38 2003/08/28 04:11:19 steve
608 * Spelling patch.
610 * Revision 1.37 2003/06/24 01:38:02 steve
611 * Various warnings fixed.
613 * Revision 1.36 2003/03/10 23:40:53 steve
614 * Keep parameter constants for the ivl_target API.
616 * Revision 1.35 2003/03/06 04:37:12 steve
617 * lex_strings.add module names earlier.
619 * Revision 1.34 2003/02/01 23:37:34 steve
620 * Allow parameter expressions to be type real.
622 * Revision 1.33 2003/01/27 05:09:17 steve
623 * Spelling fixes.
625 * Revision 1.32 2003/01/26 21:15:58 steve
626 * Rework expression parsing and elaboration to
627 * accommodate real/realtime values and expressions.
629 * Revision 1.31 2003/01/14 21:16:18 steve
630 * Move strstream to ostringstream for compatibility.
632 * Revision 1.30 2002/12/07 02:49:24 steve
633 * Named event triggers can take hierarchical names.
635 * Revision 1.29 2002/11/02 03:27:52 steve
636 * Allow named events to be referenced by
637 * hierarchical names.
639 * Revision 1.28 2002/10/19 22:59:49 steve
640 * Redo the parameter vector support to allow
641 * parameter names in range expressions.
643 * Revision 1.27 2002/08/16 05:18:27 steve
644 * Fix intermix of node functors and node delete.
646 * Revision 1.26 2002/08/12 01:34:59 steve
647 * conditional ident string using autoconfig.
649 * Revision 1.25 2002/07/03 05:34:59 steve
650 * Fix scope search for events.
652 * Revision 1.24 2002/06/25 02:39:34 steve
653 * Fix mishandling of incorect defparam error message.
655 * Revision 1.23 2001/12/03 04:47:15 steve
656 * Parser and pform use hierarchical names as hname_t
657 * objects instead of encoded strings.
659 * Revision 1.22 2001/10/20 05:21:51 steve
660 * Scope/module names are char* instead of string.