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)
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 #ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
28 * This source file contains all the implementations of the Design
29 * class declared in netlist.h.
34 # include "compiler.h"
39 : errors(0), nodes_(0), procs_(0), lcounter_(0)
43 nodes_functor_cur_
= 0;
44 nodes_functor_nxt_
= 0;
51 string
Design::local_symbol(const string
&path
)
54 res
<< path
<< "." << "_L" << lcounter_
;
60 void Design::set_precision(int val
)
62 if (val
< des_precision_
)
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_
) {
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
91 root_scope_
->set_module_name(root_scope_
->basename());
92 root_scopes_
.push_back(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()
107 const list
<NetScope
*> Design::find_root_scopes() const
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
118 NetScope
* Design::find_scope(const std::list
<hname_t
>&path
) const
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())
130 std::list
<hname_t
> tmp
= path
;
134 if (tmp
.empty()) return cur
;
136 cur
= cur
->child( tmp
.front() );
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
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 (cur
->type() == NetScope::MODULE
166 && cur
->module_name()==key
.peek_name()) {
168 /* Up references may match module name */
171 cur
= cur
->child( key
);
175 } while (!tmp
.empty());
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_
;
202 cur
->run_defparams(des
);
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
);
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
;
226 bool flag
= targ_scope
->replace_parameter(perm_name
, val
);
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
)
247 cur
->evaluate_parameters(des
);
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
++) {
264 bool range_flag
= false;
267 /* Evaluate the msb expression, if it is present. */
268 expr
= (*cur
).second
.msb
;
272 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(expr
);
276 NetExpr
*nexpr
= expr
->eval_tree();
278 cerr
<< (*cur
).second
.expr
->get_line()
279 << ": internal error: "
280 << "unable to evaluate msb expression "
281 << "for parameter " << (*cur
).first
<< ": "
289 (*cur
).second
.msb
= nexpr
;
291 tmp
= dynamic_cast<NetEConst
*>(nexpr
);
295 msb
= tmp
->value().as_long();
299 /* Evaluate the lsb expression, if it is present. */
300 expr
= (*cur
).second
.lsb
;
303 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(expr
);
307 NetExpr
*nexpr
= expr
->eval_tree();
309 cerr
<< (*cur
).second
.expr
->get_line()
310 << ": internal error: "
311 << "unable to evaluate lsb expression "
312 << "for parameter " << (*cur
).first
<< ": "
320 (*cur
).second
.lsb
= nexpr
;
322 tmp
= dynamic_cast<NetEConst
*>(nexpr
);
326 lsb
= tmp
->value().as_long();
332 /* Evaluate the parameter expression, if necessary. */
333 expr
= (*cur
).second
.expr
;
336 switch (expr
->expr_type()) {
338 if (! dynamic_cast<const NetECReal
*>(expr
)) {
340 NetExpr
*nexpr
= expr
->eval_tree();
342 cerr
<< (*cur
).second
.expr
->get_line()
343 << ": internal error: "
344 << "unable to evaluate real parameter value: "
352 (*cur
).second
.expr
= nexpr
;
358 if (! dynamic_cast<const NetEConst
*>(expr
)) {
360 // Try to evaluate the expression.
361 NetExpr
*nexpr
= expr
->eval_tree();
363 cerr
<< (*cur
).second
.expr
->get_line()
364 << ": internal error: "
365 << "unable to evaluate parameter "
373 // The evaluate worked, replace the old
374 // expression with this constant value.
377 (*cur
).second
.expr
= nexpr
;
379 // Set the signedness flag.
381 ->cast_signed( (*cur
).second
.signed_flag
);
386 cerr
<< (*cur
).second
.expr
->get_line()
387 << ": internal error: "
388 << "unhandled expression type?" << endl
;
393 /* If the parameter has range information, then make
394 sure the value is set right. */
396 unsigned long wid
= (msb
>= lsb
)? msb
- lsb
: lsb
- msb
;
399 NetEConst
*val
= dynamic_cast<NetEConst
*>((*cur
).second
.expr
);
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
);
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())
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
)
441 perm_string key
= peek_tail_name(path
);
443 if (! path
.empty()) {
444 list
<hname_t
> eval_path
= eval_scope_path(this, scope
, path
);
445 scope
= find_scope(scope
, eval_path
);
449 if (NetNet
*net
= scope
->find_signal(key
))
452 if (scope
->type() == NetScope::MODULE
)
455 scope
= scope
->parent();
461 NetFuncDef
* Design::find_function(NetScope
*scope
, const pform_name_t
&name
)
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();
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
))
483 void Design::add_node(NetNode
*net
)
485 assert(net
->design_
== 0);
487 net
->node_next_
= net
;
488 net
->node_prev_
= net
;
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
;
499 void Design::del_node(NetNode
*net
)
501 assert(net
->design_
== this);
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. */
516 nodes_
= net
->node_prev_
;
521 net
->node_next_
->node_prev_
= net
->node_prev_
;
522 net
->node_prev_
->node_next_
= net
->node_next_
;
528 void Design::add_process(NetProcTop
*pro
)
534 void Design::delete_process(NetProcTop
*top
)
541 NetProcTop
*cur
= procs_
;
542 while (cur
->next_
!= top
) {
547 cur
->next_
= top
->next_
;
550 if (procs_idx_
== top
)
551 procs_idx_
= top
->next_
;
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
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
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.