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)
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
26 * This source file contains all the implementations of the Design
27 * class declared in netlist.h.
32 # include "compiler.h"
35 # include "ivl_assert.h"
38 : errors(0), nodes_(0), procs_(0), lcounter_(0)
42 nodes_functor_cur_
= 0;
43 nodes_functor_nxt_
= 0;
50 string
Design::local_symbol(const string
&path
)
53 res
<< path
<< "." << "_L" << lcounter_
;
59 void Design::set_precision(int val
)
61 if (val
< des_precision_
)
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_
) {
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
90 root_scope_
->set_module_name(root_scope_
->basename());
91 root_scopes_
.push_back(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()
106 const list
<NetScope
*> Design::find_root_scopes() const
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
117 NetScope
* Design::find_scope(const std::list
<hname_t
>&path
) const
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())
129 std::list
<hname_t
> tmp
= path
;
133 if (tmp
.empty()) return cur
;
135 cur
= cur
->child( tmp
.front() );
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
158 for ( ; scope
; scope
= scope
->parent()) {
160 std::list
<hname_t
> tmp
= path
;
162 NetScope
*cur
= scope
;
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 */
175 cur
= cur
->child( key
);
179 } while (!tmp
.empty());
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_
;
206 cur
->run_defparams(des
);
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
);
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
;
230 bool flag
= targ_scope
->replace_parameter(perm_name
, val
);
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
)
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
;
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
;
286 /* Evaluate the parameter expression, if necessary. */
287 NetExpr
*expr
= (*cur
).second
.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()) {
299 if (! dynamic_cast<const NetECReal
*>(expr
)) {
300 cerr
<< expr
->get_fileline()
301 << ": internal error: "
302 << "unable to evaluate real parameter value: "
311 if (! dynamic_cast<const NetEConst
*>(expr
)) {
312 cerr
<< expr
->get_fileline()
313 << ": internal error: "
314 << "unable to evaluate parameter "
316 << " value: " << *expr
<< endl
;
323 cerr
<< expr
->get_fileline()
324 << ": internal error: "
325 << "unhandled expression type?" << endl
;
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. */
335 unsigned long wid
= (msb
>= lsb
)? msb
- lsb
: lsb
- msb
;
338 NetEConst
*val
= dynamic_cast<NetEConst
*>(expr
);
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
);
350 val
= new NetEConst(tmp
);
355 // If there are no value ranges to test the value against,
357 if ((*cur
).second
.range
== 0) {
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)
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())
382 else if (value
< tmp
->value())
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())
391 else if (value
> tmp
->value())
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) {
402 // OH NO! In an excluded range. signal an error.
407 // If we found no from range that contains the
408 // value, then report an error.
410 cerr
<< val
->get_fileline() << ": error: "
411 << "Parameter value " << value
412 << " is out of range for parameter " << (*cur
).first
418 void NetScope::evaluate_parameter_real_(Design
*des
, param_ref_t cur
)
420 NetExpr
*expr
= (*cur
).second
.expr
;
426 switch (expr
->expr_type()) {
428 if (NetECReal
*tmp
= dynamic_cast<NetECReal
*>(expr
)) {
431 ivl_assert(*expr
, 0);
437 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(expr
)) {
438 verireal
val (tmp
->value().as_long());
439 res
= new NetECReal(val
);
442 ivl_assert(*expr
, 0);
447 ivl_assert(*expr
, 0);
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)
461 if (value_range
->low_expr
) {
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
)
467 else if (value
< tmp
)
471 if (value_range
->high_expr
) {
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
)
477 else if (value
> tmp
)
481 if (value_range
->exclude_flag
== false) {
486 // All the above tests failed, so we must have tripped
493 cerr
<< res
->get_fileline() << ": error: "
494 << "Parameter value " << value
495 << " is out of range for parameter " << (*cur
).first
501 void NetScope::evaluate_parameters(Design
*des
)
505 cur
->evaluate_parameters(des
);
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
) {
521 evaluate_parameter_logic_(des
, cur
);
525 evaluate_parameter_real_(des
, cur
);
529 cerr
<< (*cur
).second
.get_fileline() << ": internal error: "
530 << "Unexpected expression type " << (*cur
).second
.type
532 ivl_assert((*cur
).second
, 0);
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())
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
)
561 perm_string key
= peek_tail_name(path
);
563 if (! path
.empty()) {
564 list
<hname_t
> eval_path
= eval_scope_path(this, scope
, path
);
565 scope
= find_scope(scope
, eval_path
);
569 if (NetNet
*net
= scope
->find_signal(key
))
572 if (scope
->type() == NetScope::MODULE
)
575 scope
= scope
->parent();
581 NetFuncDef
* Design::find_function(NetScope
*scope
, const pform_name_t
&name
)
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();
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
))
603 void Design::add_node(NetNode
*net
)
605 assert(net
->design_
== 0);
607 net
->node_next_
= net
;
608 net
->node_prev_
= net
;
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
;
619 void Design::del_node(NetNode
*net
)
621 assert(net
->design_
== this);
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. */
636 nodes_
= net
->node_prev_
;
641 net
->node_next_
->node_prev_
= net
->node_prev_
;
642 net
->node_prev_
->node_next_
= net
->node_next_
;
648 void Design::add_process(NetProcTop
*pro
)
654 void Design::delete_process(NetProcTop
*top
)
661 NetProcTop
*cur
= procs_
;
662 while (cur
->next_
!= top
) {
667 cur
->next_
= top
->next_
;
670 if (procs_idx_
== top
)
671 procs_idx_
= top
->next_
;