2 * Copyright (c) 2000-2008 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
21 # include "compiler.h"
27 # include "ivl_assert.h"
30 * The NetScope class keeps a scope tree organized. Each node of the
31 * scope tree points to its parent, its right sibling and its leftmost
32 * child. The root node has no parent or siblings. The node stores the
33 * name of the scope. The complete hierarchical name of the scope is
34 * formed by appending the path of scopes from the root to the scope
38 NetScope::NetScope(NetScope
*up
, const hname_t
&n
, NetScope::TYPE t
)
39 : type_(t
), up_(up
), sib_(0), sub_(0)
46 default_nettype_
= up
->default_nettype();
47 time_unit_
= up
->time_unit();
48 time_prec_
= up
->time_precision();
52 default_nettype_
= NetNet::NONE
;
65 case NetScope::MODULE
:
66 module_name_
= perm_string();
68 default: /* BEGIN_END and FORK_JOIN, do nothing */
80 /* name_ and module_name_ are perm-allocated. */
83 void NetScope::set_line(const LineInfo
*info
)
85 file_
= info
->get_file();
87 lineno_
= info
->get_lineno();
88 def_lineno_
= lineno_
;
91 void NetScope::set_line(perm_string file
, unsigned lineno
)
99 void NetScope::set_line(perm_string file
, perm_string def_file
,
100 unsigned lineno
, unsigned def_lineno
)
103 def_file_
= def_file
;
105 def_lineno_
= def_lineno
;
108 NetExpr
* NetScope::set_parameter(perm_string key
, NetExpr
*expr
,
109 ivl_variable_type_t type
,
110 NetExpr
*msb
, NetExpr
*lsb
, bool signed_flag
,
111 NetScope::range_t
*range_list
,
112 const LineInfo
&file_line
)
114 param_expr_t
&ref
= parameters
[key
];
115 NetExpr
* res
= ref
.expr
;
120 ref
.signed_flag
= signed_flag
;
121 ivl_assert(file_line
, ref
.range
== 0);
122 ref
.range
= range_list
;
123 ref
.set_line(file_line
);
127 bool NetScope::auto_name(const char*prefix
, char pad
, const char* suffix
)
130 int pad_pos
= strlen(prefix
);
131 int max_pos
= sizeof(tmp
) - strlen(suffix
) - 1;
132 strncpy(tmp
, prefix
, sizeof(tmp
));
133 while (pad_pos
<= max_pos
) {
134 strcat(tmp
+ pad_pos
, suffix
);
135 hname_t
new_name(lex_strings
.make(tmp
));
136 if (!up_
->child(new_name
)) {
140 tmp
[pad_pos
++] = pad
;
146 * Return false if the parameter does not already exist.
147 * A parameter is not automatically created.
149 bool NetScope::replace_parameter(perm_string key
, NetExpr
*expr
)
153 if (parameters
.find(key
) != parameters
.end()) {
154 param_expr_t
&ref
= parameters
[key
];
165 * This is not really complete (msb, lsb, sign). It is currently only
166 * used to add a genver to the local parameter list.
168 NetExpr
* NetScope::set_localparam(perm_string key
, NetExpr
*expr
,
169 const LineInfo
&file_line
)
171 param_expr_t
&ref
= localparams
[key
];
172 NetExpr
* res
= ref
.expr
;
176 ref
.signed_flag
= false;
177 ref
.set_line(file_line
);
182 * NOTE: This method takes a const char* as a key to lookup a
183 * parameter, because we don't save that pointer. However, due to the
184 * way the map<> template works, we need to *cheat* and use the
185 * perm_string::literal method to fake the compiler into doing the
186 * compare without actually creating a perm_string.
188 const NetExpr
* NetScope::get_parameter(const char* key
,
190 const NetExpr
*&lsb
) const
192 map
<perm_string
,param_expr_t
>::const_iterator idx
;
194 idx
= parameters
.find(perm_string::literal(key
));
195 if (idx
!= parameters
.end()) {
196 msb
= (*idx
).second
.msb
;
197 lsb
= (*idx
).second
.lsb
;
198 return (*idx
).second
.expr
;
201 idx
= localparams
.find(perm_string::literal(key
));
202 if (idx
!= localparams
.end()) {
203 msb
= (*idx
).second
.msb
;
204 lsb
= (*idx
).second
.lsb
;
205 return (*idx
).second
.expr
;
210 map
<perm_string
,NetScope::param_expr_t
>::iterator
NetScope::find_parameter(perm_string key
)
212 map
<perm_string
,param_expr_t
>::iterator idx
;
214 idx
= parameters
.find(key
);
215 if (idx
!= parameters
.end())
218 idx
= localparams
.find(perm_string::literal(key
));
219 if (idx
!= localparams
.end())
222 return (map
<perm_string
,param_expr_t
>::iterator
) 0;
225 NetScope::TYPE
NetScope::type() const
230 void NetScope::set_task_def(NetTaskDef
*def
)
232 assert( type_
== TASK
);
233 assert( task_
== 0 );
237 NetTaskDef
* NetScope::task_def()
239 assert( type_
== TASK
);
243 const NetTaskDef
* NetScope::task_def() const
245 assert( type_
== TASK
);
249 void NetScope::set_func_def(NetFuncDef
*def
)
251 assert( type_
== FUNC
);
252 assert( func_
== 0 );
256 NetFuncDef
* NetScope::func_def()
258 assert( type_
== FUNC
);
261 bool NetScope::in_func()
263 return (type_
== FUNC
) ? true : false;
266 const NetFuncDef
* NetScope::func_def() const
268 assert( type_
== FUNC
);
272 void NetScope::set_module_name(perm_string n
)
274 assert(type_
== MODULE
);
275 module_name_
= n
; /* NOTE: n mus have been permallocated. */
278 perm_string
NetScope::module_name() const
280 assert(type_
== MODULE
);
284 void NetScope::time_unit(int val
)
289 void NetScope::time_precision(int val
)
294 int NetScope::time_unit() const
299 int NetScope::time_precision() const
304 void NetScope::default_nettype(NetNet::Type nt
)
306 default_nettype_
= nt
;
309 NetNet::Type
NetScope::default_nettype() const
311 return default_nettype_
;
314 perm_string
NetScope::basename() const
316 return name_
.peek_name();
319 void NetScope::add_event(NetEvent
*ev
)
321 assert(ev
->scope_
== 0);
323 ev
->snext_
= events_
;
327 void NetScope::rem_event(NetEvent
*ev
)
329 assert(ev
->scope_
== this);
332 events_
= ev
->snext_
;
335 NetEvent
*cur
= events_
;
336 while (cur
->snext_
!= ev
) {
340 cur
->snext_
= ev
->snext_
;
347 NetEvent
* NetScope::find_event(perm_string name
)
349 for (NetEvent
*cur
= events_
; cur
; cur
= cur
->snext_
)
350 if (cur
->name() == name
)
356 void NetScope::add_signal(NetNet
*net
)
359 net
->sig_next_
= net
;
360 net
->sig_prev_
= net
;
362 net
->sig_next_
= signals_
->sig_next_
;
363 net
->sig_prev_
= signals_
;
364 net
->sig_next_
->sig_prev_
= net
;
365 net
->sig_prev_
->sig_next_
= net
;
370 void NetScope::rem_signal(NetNet
*net
)
372 assert(net
->scope() == this);
374 signals_
= net
->sig_prev_
;
376 if (signals_
== net
) {
379 net
->sig_prev_
->sig_next_
= net
->sig_next_
;
380 net
->sig_next_
->sig_prev_
= net
->sig_prev_
;
385 * This method looks for a signal within the current scope. The name
386 * is assumed to be the base name of the signal, so no sub-scopes are
389 NetNet
* NetScope::find_signal(perm_string key
)
394 NetNet
*cur
= signals_
;
396 if (cur
->name() == key
)
398 cur
= cur
->sig_prev_
;
399 } while (cur
!= signals_
);
404 * This method locates a child scope by name. The name is the simple
405 * name of the child, no hierarchy is searched.
407 NetScope
* NetScope::child(const hname_t
&name
)
409 if (sub_
== 0) return 0;
412 while (cur
->name_
!= name
) {
413 if (cur
->sib_
== 0) return 0;
420 const NetScope
* NetScope::child(const hname_t
&name
) const
422 if (sub_
== 0) return 0;
425 while (cur
->name_
!= name
) {
426 if (cur
->sib_
== 0) return 0;
433 NetScope
* NetScope::parent()
438 const NetScope
* NetScope::parent() const
443 perm_string
NetScope::local_symbol()
446 res
<< "_s" << (lcounter_
++);
447 return lex_strings
.make(res
.str());
450 string
NetScope::local_hsymbol()
452 return string(name()) + "." + string(local_symbol());