Merge branch 'master' into verilog-ams
[sverilog.git] / net_design.cc
blob071dd340cb9b45b85a537866fec44727618e1ab2
1 /*
2 * Copyright (c) 2000-2007 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
20 # include "config.h"
22 # include <iostream>
23 # include <cstdlib>
26 * This source file contains all the implementations of the Design
27 * class declared in netlist.h.
30 # include "netlist.h"
31 # include "util.h"
32 # include "compiler.h"
33 # include "netmisc.h"
34 # include <sstream>
35 # include "ivl_assert.h"
37 Design:: Design()
38 : errors(0), nodes_(0), procs_(0), lcounter_(0)
40 procs_idx_ = 0;
41 des_precision_ = 0;
42 nodes_functor_cur_ = 0;
43 nodes_functor_nxt_ = 0;
46 Design::~Design()
50 string Design::local_symbol(const string&path)
52 ostringstream res;
53 res << path << "." << "_L" << lcounter_;
54 lcounter_ += 1;
56 return res.str();
59 void Design::set_precision(int val)
61 if (val < des_precision_)
62 des_precision_ = val;
65 int Design::get_precision() const
67 return des_precision_;
70 uint64_t Design::scale_to_precision(uint64_t val,
71 const NetScope*scope) const
73 int units = scope->time_unit();
74 assert( units >= des_precision_ );
76 while (units > des_precision_) {
77 units -= 1;
78 val *= 10;
81 return val;
84 NetScope* Design::make_root_scope(perm_string root)
86 NetScope *root_scope_;
87 root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
88 /* This relies on the fact that the basename return value is
89 permallocated. */
90 root_scope_->set_module_name(root_scope_->basename());
91 root_scopes_.push_back(root_scope_);
92 return root_scope_;
95 NetScope* Design::find_root_scope()
97 assert(root_scopes_.front());
98 return root_scopes_.front();
101 list<NetScope*> Design::find_root_scopes()
103 return root_scopes_;
106 const list<NetScope*> Design::find_root_scopes() const
108 return root_scopes_;
112 * This method locates a scope in the design, given its rooted
113 * hierarchical name. Each component of the key is used to scan one
114 * more step down the tree until the name runs out or the search
115 * fails.
117 NetScope* Design::find_scope(const std::list<hname_t>&path) const
119 if (path.empty())
120 return 0;
122 for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
123 ; scope != root_scopes_.end(); scope++) {
125 NetScope*cur = *scope;
126 if (path.front() != cur->fullname())
127 continue;
129 std::list<hname_t> tmp = path;
130 tmp.pop_front();
132 while (cur) {
133 if (tmp.empty()) return cur;
135 cur = cur->child( tmp.front() );
137 tmp.pop_front();
142 return 0;
146 * This is a relative lookup of a scope by name. The starting point is
147 * the scope parameter within which I start looking for the scope. If
148 * I do not find the scope within the passed scope, start looking in
149 * parent scopes until I find it, or I run out of parent scopes.
151 NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path,
152 NetScope::TYPE type) 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 we are looking for a module or we are not
166 * looking at the last path component check for
167 * a name match (second line). */
168 if (cur->type() == NetScope::MODULE
169 && (type == NetScope::MODULE || tmp.size() > 1)
170 && cur->module_name()==key.peek_name()) {
172 /* Up references may match module name */
174 } else {
175 cur = cur->child( key );
176 if (cur == 0) break;
178 tmp.pop_front();
179 } while (!tmp.empty());
181 if (cur) return cur;
184 // Last chance. Look for the name starting at the root.
185 return find_scope(path);
189 * This method runs through the scope, noticing the defparam
190 * statements that were collected during the elaborate_scope pass and
191 * applying them to the target parameters. The implementation actually
192 * works by using a specialized method from the NetScope class that
193 * does all the work for me.
195 void Design::run_defparams()
197 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
198 scope != root_scopes_.end(); scope++)
199 (*scope)->run_defparams(this);
202 void NetScope::run_defparams(Design*des)
204 { NetScope*cur = sub_;
205 while (cur) {
206 cur->run_defparams(des);
207 cur = cur->sib_;
211 map<pform_name_t,NetExpr*>::const_iterator pp;
212 for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
213 NetExpr*val = (*pp).second;
214 pform_name_t path = (*pp).first;
216 perm_string perm_name = peek_tail_name(path);
217 path.pop_back();
219 list<hname_t> eval_path = eval_scope_path(des, this, path);
221 /* If there is no path on the name, then the targ_scope
222 is the current scope. */
223 NetScope*targ_scope = des->find_scope(this, eval_path);
224 if (targ_scope == 0) {
225 cerr << val->get_fileline() << ": warning: scope of " <<
226 path << "." << perm_name << " not found." << endl;
227 continue;
230 bool flag = targ_scope->replace_parameter(perm_name, val);
231 if (! flag) {
232 cerr << val->get_fileline() << ": warning: parameter "
233 << perm_name << " not found in "
234 << scope_path(targ_scope) << "." << endl;
240 void Design::evaluate_parameters()
242 for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
243 scope != root_scopes_.end(); scope++)
244 (*scope)->evaluate_parameters(this);
247 void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
249 long msb = 0;
250 long lsb = 0;
251 bool range_flag = false;
253 /* Evaluate the msb expression, if it is present. */
254 if ((*cur).second.msb) {
255 eval_expr((*cur).second.msb);
256 if (! eval_as_long(msb, (*cur).second.msb)) {
257 cerr << (*cur).second.expr->get_fileline()
258 << ": internal error: "
259 << "unable to evaluate msb expression "
260 << "for parameter " << (*cur).first << ": "
261 << *(*cur).second.msb << endl;
262 des->errors += 1;
263 return;
266 range_flag = true;
269 /* Evaluate the lsb expression, if it is present. */
270 if ((*cur).second.lsb) {
271 eval_expr((*cur).second.lsb);
272 if (! eval_as_long(lsb, (*cur).second.lsb)) {
273 cerr << (*cur).second.expr->get_fileline()
274 << ": internal error: "
275 << "unable to evaluate lsb expression "
276 << "for parameter " << (*cur).first << ": "
277 << *(*cur).second.lsb << endl;
278 des->errors += 1;
279 return;
282 range_flag = true;
286 /* Evaluate the parameter expression, if necessary. */
287 NetExpr*expr = (*cur).second.expr;
288 assert(expr);
290 eval_expr(expr);
292 /* The eval_expr may delete any replace the expr pointer, so the
293 second.expr value cannot be relied on. Might as well replace
294 it now with the expression that we evaluated. */
295 (*cur).second.expr = expr;
297 switch (expr->expr_type()) {
298 case IVL_VT_REAL:
299 if (! dynamic_cast<const NetECReal*>(expr)) {
300 cerr << expr->get_fileline()
301 << ": internal error: "
302 << "unable to evaluate real parameter value: "
303 << *expr << endl;
304 des->errors += 1;
305 return;
307 break;
309 case IVL_VT_LOGIC:
310 case IVL_VT_BOOL:
311 if (! dynamic_cast<const NetEConst*>(expr)) {
312 cerr << expr->get_fileline()
313 << ": internal error: "
314 << "unable to evaluate parameter "
315 << (*cur).first
316 << " value: " << *expr << endl;
317 des->errors += 1;
318 return;
320 break;
322 default:
323 cerr << expr->get_fileline()
324 << ": internal error: "
325 << "unhandled expression type?" << endl;
326 des->errors += 1;
327 return;
330 /* If the parameter has range information, then make
331 sure the value is set right. Note that if the
332 parameter doesn't have an explicit range, then it
333 will get the signedness from the expression itself. */
334 if (range_flag) {
335 unsigned long wid = (msb >= lsb)? msb - lsb : lsb - msb;
336 wid += 1;
338 NetEConst*val = dynamic_cast<NetEConst*>(expr);
339 assert(val);
341 verinum value = val->value();
343 if (! (value.has_len()
344 && (value.len() == wid)
345 && (value.has_sign() == (*cur).second.signed_flag))) {
347 verinum tmp (value, wid);
348 tmp.has_sign ( (*cur).second.signed_flag );
349 delete val;
350 val = new NetEConst(tmp);
351 expr = val;
355 // If there are no value ranges to test the value against,
356 // then we are done.
357 if ((*cur).second.range == 0) {
358 return;
361 NetEConst*val = dynamic_cast<NetEConst*>((*cur).second.expr);
362 ivl_assert(*(*cur).second.expr, (*cur).second.expr);
363 ivl_assert(*(*cur).second.expr, val);
365 verinum value = val->value();
367 bool from_flag = (*cur).second.range == 0? true : false;
368 for (range_t*value_range = (*cur).second.range
369 ; value_range ; value_range = value_range->next) {
371 // If we already know that the value is
372 // within a "from" range, then do not test
373 // any more of the from ranges.
374 if (from_flag && value_range->exclude_flag==false)
375 continue;
377 if (value_range->low_expr) {
378 NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->low_expr);
379 ivl_assert(*value_range->low_expr, tmp);
380 if (value_range->low_open_flag && value <= tmp->value())
381 continue;
382 else if (value < tmp->value())
383 continue;
386 if (value_range->high_expr) {
387 NetEConst*tmp = dynamic_cast<NetEConst*>(value_range->high_expr);
388 ivl_assert(*value_range->high_expr, tmp);
389 if (value_range->high_open_flag && value >= tmp->value())
390 continue;
391 else if (value > tmp->value())
392 continue;
395 // Within the range. If this is a "from"
396 // range, then set the from_flag and continue.
397 if (value_range->exclude_flag == false) {
398 from_flag = true;
399 continue;
402 // OH NO! In an excluded range. signal an error.
403 from_flag = false;
404 break;
407 // If we found no from range that contains the
408 // value, then report an error.
409 if (! from_flag) {
410 cerr << val->get_fileline() << ": error: "
411 << "Parameter value " << value
412 << " is out of range for parameter " << (*cur).first
413 << "." << endl;
414 des->errors += 1;
418 void NetScope::evaluate_parameter_real_(Design*des, param_ref_t cur)
420 NetExpr*expr = (*cur).second.expr;
421 assert(expr);
423 NetECReal*res = 0;
424 eval_expr(expr);
426 switch (expr->expr_type()) {
427 case IVL_VT_REAL:
428 if (NetECReal*tmp = dynamic_cast<NetECReal*>(expr)) {
429 res = tmp;
430 } else {
431 ivl_assert(*expr, 0);
433 break;
435 case IVL_VT_LOGIC:
436 case IVL_VT_BOOL:
437 if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
438 verireal val (tmp->value().as_long());
439 res = new NetECReal(val);
440 res->set_line(*tmp);
441 } else {
442 ivl_assert(*expr, 0);
444 break;
446 default:
447 ivl_assert(*expr, 0);
448 break;
451 (*cur).second.expr = res;
452 double value = res->value().as_double();
454 bool from_flag = (*cur).second.range == 0? true : false;
455 for (range_t*value_range = (*cur).second.range
456 ; value_range ; value_range = value_range->next) {
458 if (from_flag && value_range->exclude_flag==false)
459 continue;
461 if (value_range->low_expr) {
462 double tmp;
463 bool flag = eval_as_double(tmp, value_range->low_expr);
464 ivl_assert(*value_range->low_expr, flag);
465 if (value_range->low_open_flag && value <= tmp)
466 continue;
467 else if (value < tmp)
468 continue;
471 if (value_range->high_expr) {
472 double tmp;
473 bool flag = eval_as_double(tmp, value_range->high_expr);
474 ivl_assert(*value_range->high_expr, flag);
475 if (value_range->high_open_flag && value >= tmp)
476 continue;
477 else if (value > tmp)
478 continue;
481 if (value_range->exclude_flag == false) {
482 from_flag = true;
483 continue;
486 // All the above tests failed, so we must have tripped
487 // an exclude rule.
488 from_flag = false;
489 break;
492 if (! from_flag) {
493 cerr << res->get_fileline() << ": error: "
494 << "Parameter value " << value
495 << " is out of range for parameter " << (*cur).first
496 << "." << endl;
497 des->errors += 1;
501 void NetScope::evaluate_parameters(Design*des)
503 NetScope*cur = sub_;
504 while (cur) {
505 cur->evaluate_parameters(des);
506 cur = cur->sib_;
510 // Evaluate the parameter values. The parameter expressions
511 // have already been elaborated and replaced by the scope
512 // scanning code. Now the parameter expression can be fully
513 // evaluated, or it cannot be evaluated at all.
515 for (param_ref_t cur = parameters.begin()
516 ; cur != parameters.end() ; cur ++) {
518 switch ((*cur).second.type) {
519 case IVL_VT_BOOL:
520 case IVL_VT_LOGIC:
521 evaluate_parameter_logic_(des, cur);
522 break;
524 case IVL_VT_REAL:
525 evaluate_parameter_real_(des, cur);
526 break;
528 default:
529 cerr << (*cur).second.get_fileline() << ": internal error: "
530 << "Unexpected expression type " << (*cur).second.type
531 << "." << endl;
532 ivl_assert((*cur).second, 0);
533 break;
539 const char* Design::get_flag(const string&key) const
541 map<string,const char*>::const_iterator tmp = flags_.find(key);
542 if (tmp == flags_.end())
543 return "";
544 else
545 return (*tmp).second;
549 * This method looks for a signal (reg, wire, whatever) starting at
550 * the specified scope. If the name is hierarchical, it is split into
551 * scope and name and the scope used to find the proper starting point
552 * for the real search.
554 * It is the job of this function to properly implement Verilog scope
555 * rules as signals are concerned.
557 NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
559 assert(scope);
561 perm_string key = peek_tail_name(path);
562 path.pop_back();
563 if (! path.empty()) {
564 list<hname_t> eval_path = eval_scope_path(this, scope, path);
565 scope = find_scope(scope, eval_path);
568 while (scope) {
569 if (NetNet*net = scope->find_signal(key))
570 return net;
572 if (scope->type() == NetScope::MODULE)
573 break;
575 scope = scope->parent();
578 return 0;
581 NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
583 assert(scope);
585 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
586 NetScope*func = find_scope(scope, eval_path, NetScope::FUNC);
587 if (func && (func->type() == NetScope::FUNC))
588 return func->func_def();
590 return 0;
593 NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
595 std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
596 NetScope*task = find_scope(scope, eval_path, NetScope::TASK);
597 if (task && (task->type() == NetScope::TASK))
598 return task;
600 return 0;
603 void Design::add_node(NetNode*net)
605 assert(net->design_ == 0);
606 if (nodes_ == 0) {
607 net->node_next_ = net;
608 net->node_prev_ = net;
609 } else {
610 net->node_next_ = nodes_->node_next_;
611 net->node_prev_ = nodes_;
612 net->node_next_->node_prev_ = net;
613 net->node_prev_->node_next_ = net;
615 nodes_ = net;
616 net->design_ = this;
619 void Design::del_node(NetNode*net)
621 assert(net->design_ == this);
622 assert(net != 0);
624 /* Interact with the Design::functor method by manipulating the
625 cur and nxt pointers that it is using. */
626 if (net == nodes_functor_nxt_)
627 nodes_functor_nxt_ = nodes_functor_nxt_->node_next_;
628 if (net == nodes_functor_nxt_)
629 nodes_functor_nxt_ = 0;
631 if (net == nodes_functor_cur_)
632 nodes_functor_cur_ = 0;
634 /* Now perform the actual delete. */
635 if (nodes_ == net)
636 nodes_ = net->node_prev_;
638 if (nodes_ == net) {
639 nodes_ = 0;
640 } else {
641 net->node_next_->node_prev_ = net->node_prev_;
642 net->node_prev_->node_next_ = net->node_next_;
645 net->design_ = 0;
648 void Design::add_process(NetProcTop*pro)
650 pro->next_ = procs_;
651 procs_ = pro;
654 void Design::delete_process(NetProcTop*top)
656 assert(top);
657 if (procs_ == top) {
658 procs_ = top->next_;
660 } else {
661 NetProcTop*cur = procs_;
662 while (cur->next_ != top) {
663 assert(cur->next_);
664 cur = cur->next_;
667 cur->next_ = top->next_;
670 if (procs_idx_ == top)
671 procs_idx_ = top->next_;
673 delete top;