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"
28 * The NetScope class keeps a scope tree organized. Each node of the
29 * scope tree points to its parent, its right sibling and its leftmost
30 * child. The root node has no parent or siblings. The node stores the
31 * name of the scope. The complete hierarchical name of the scope is
32 * formed by appending the path of scopes from the root to the scope
36 NetScope::NetScope(NetScope
*up
, const hname_t
&n
, NetScope::TYPE t
)
37 : type_(t
), up_(up
), sib_(0), sub_(0)
44 default_nettype_
= up
->default_nettype();
45 time_unit_
= up
->time_unit();
46 time_prec_
= up
->time_precision();
50 default_nettype_
= NetNet::NONE
;
63 case NetScope::MODULE
:
64 module_name_
= perm_string();
66 default: /* BEGIN_END and FORK_JOIN, do nothing */
78 /* name_ and module_name_ are perm-allocated. */
81 void NetScope::set_line(const LineInfo
*info
)
83 file_
= info
->get_file();
85 lineno_
= info
->get_lineno();
86 def_lineno_
= lineno_
;
89 void NetScope::set_line(perm_string file
, unsigned lineno
)
97 void NetScope::set_line(perm_string file
, perm_string def_file
,
98 unsigned lineno
, unsigned def_lineno
)
101 def_file_
= def_file
;
103 def_lineno_
= def_lineno
;
106 NetExpr
* NetScope::set_parameter(perm_string key
, NetExpr
*expr
,
107 NetExpr
*msb
, NetExpr
*lsb
, bool signed_flag
,
108 perm_string file
, unsigned lineno
)
110 param_expr_t
&ref
= parameters
[key
];
111 NetExpr
* res
= ref
.expr
;
115 ref
.signed_flag
= signed_flag
;
121 bool NetScope::auto_name(const char*prefix
, char pad
, const char* suffix
)
124 int pad_pos
= strlen(prefix
);
125 int max_pos
= sizeof(tmp
) - strlen(suffix
) - 1;
126 strncpy(tmp
, prefix
, sizeof(tmp
));
127 while (pad_pos
<= max_pos
) {
128 strcat(tmp
+ pad_pos
, suffix
);
129 hname_t
new_name(lex_strings
.make(tmp
));
130 if (!up_
->child(new_name
)) {
134 tmp
[pad_pos
++] = pad
;
140 * Return false if the parameter does not already exist.
141 * A parameter is not automatically created.
143 bool NetScope::replace_parameter(perm_string key
, NetExpr
*expr
)
147 if (parameters
.find(key
) != parameters
.end()) {
148 param_expr_t
&ref
= parameters
[key
];
159 * This is not really complete (msb, lsb, sign). It is currently only
160 * used to add a genver to the local parameter list.
162 NetExpr
* NetScope::set_localparam(perm_string key
, NetExpr
*expr
,
163 perm_string file
, unsigned lineno
)
165 param_expr_t
&ref
= localparams
[key
];
166 NetExpr
* res
= ref
.expr
;
170 ref
.signed_flag
= false;
177 * NOTE: This method takes a const char* as a key to lookup a
178 * parameter, because we don't save that pointer. However, due to the
179 * way the map<> template works, we need to *cheat* and use the
180 * perm_string::literal method to fake the compiler into doing the
181 * compare without actually creating a perm_string.
183 const NetExpr
* NetScope::get_parameter(const char* key
,
185 const NetExpr
*&lsb
) const
187 map
<perm_string
,param_expr_t
>::const_iterator idx
;
189 idx
= parameters
.find(perm_string::literal(key
));
190 if (idx
!= parameters
.end()) {
191 msb
= (*idx
).second
.msb
;
192 lsb
= (*idx
).second
.lsb
;
193 return (*idx
).second
.expr
;
196 idx
= localparams
.find(perm_string::literal(key
));
197 if (idx
!= localparams
.end()) {
198 msb
= (*idx
).second
.msb
;
199 lsb
= (*idx
).second
.lsb
;
200 return (*idx
).second
.expr
;
206 NetScope::TYPE
NetScope::type() const
211 void NetScope::set_task_def(NetTaskDef
*def
)
213 assert( type_
== TASK
);
214 assert( task_
== 0 );
218 NetTaskDef
* NetScope::task_def()
220 assert( type_
== TASK
);
224 const NetTaskDef
* NetScope::task_def() const
226 assert( type_
== TASK
);
230 void NetScope::set_func_def(NetFuncDef
*def
)
232 assert( type_
== FUNC
);
233 assert( func_
== 0 );
237 NetFuncDef
* NetScope::func_def()
239 assert( type_
== FUNC
);
242 bool NetScope::in_func()
244 return (type_
== FUNC
) ? true : false;
247 const NetFuncDef
* NetScope::func_def() const
249 assert( type_
== FUNC
);
253 void NetScope::set_module_name(perm_string n
)
255 assert(type_
== MODULE
);
256 module_name_
= n
; /* NOTE: n mus have been permallocated. */
259 perm_string
NetScope::module_name() const
261 assert(type_
== MODULE
);
265 void NetScope::time_unit(int val
)
270 void NetScope::time_precision(int val
)
275 int NetScope::time_unit() const
280 int NetScope::time_precision() const
285 void NetScope::default_nettype(NetNet::Type nt
)
287 default_nettype_
= nt
;
290 NetNet::Type
NetScope::default_nettype() const
292 return default_nettype_
;
295 perm_string
NetScope::basename() const
297 return name_
.peek_name();
300 void NetScope::add_event(NetEvent
*ev
)
302 assert(ev
->scope_
== 0);
304 ev
->snext_
= events_
;
308 void NetScope::rem_event(NetEvent
*ev
)
310 assert(ev
->scope_
== this);
313 events_
= ev
->snext_
;
316 NetEvent
*cur
= events_
;
317 while (cur
->snext_
!= ev
) {
321 cur
->snext_
= ev
->snext_
;
328 NetEvent
* NetScope::find_event(perm_string name
)
330 for (NetEvent
*cur
= events_
; cur
; cur
= cur
->snext_
)
331 if (cur
->name() == name
)
337 void NetScope::add_signal(NetNet
*net
)
340 net
->sig_next_
= net
;
341 net
->sig_prev_
= net
;
343 net
->sig_next_
= signals_
->sig_next_
;
344 net
->sig_prev_
= signals_
;
345 net
->sig_next_
->sig_prev_
= net
;
346 net
->sig_prev_
->sig_next_
= net
;
351 void NetScope::rem_signal(NetNet
*net
)
353 assert(net
->scope() == this);
355 signals_
= net
->sig_prev_
;
357 if (signals_
== net
) {
360 net
->sig_prev_
->sig_next_
= net
->sig_next_
;
361 net
->sig_next_
->sig_prev_
= net
->sig_prev_
;
366 * This method looks for a signal within the current scope. The name
367 * is assumed to be the base name of the signal, so no sub-scopes are
370 NetNet
* NetScope::find_signal(perm_string key
)
375 NetNet
*cur
= signals_
;
377 if (cur
->name() == key
)
379 cur
= cur
->sig_prev_
;
380 } while (cur
!= signals_
);
385 * This method locates a child scope by name. The name is the simple
386 * name of the child, no hierarchy is searched.
388 NetScope
* NetScope::child(const hname_t
&name
)
390 if (sub_
== 0) return 0;
393 while (cur
->name_
!= name
) {
394 if (cur
->sib_
== 0) return 0;
401 const NetScope
* NetScope::child(const hname_t
&name
) const
403 if (sub_
== 0) return 0;
406 while (cur
->name_
!= name
) {
407 if (cur
->sib_
== 0) return 0;
414 NetScope
* NetScope::parent()
419 const NetScope
* NetScope::parent() const
424 perm_string
NetScope::local_symbol()
427 res
<< "_s" << (lcounter_
++);
428 return lex_strings
.make(res
.str());
431 string
NetScope::local_hsymbol()
433 return string(name()) + "." + string(local_symbol());