Merge branch 'master' into verilog-ams
[sverilog.git] / net_scope.cc
blob4425a2a49ba9a23aacd059c3042d12ff7f216304
1 /*
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)
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"
21 # include "compiler.h"
23 # include "netlist.h"
24 # include <cstring>
25 # include <cstdlib>
26 # include <sstream>
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
35 * in question.
38 NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
39 : type_(t), up_(up), sib_(0), sub_(0)
41 signals_ = 0;
42 events_ = 0;
43 lcounter_ = 0;
45 if (up) {
46 default_nettype_ = up->default_nettype();
47 time_unit_ = up->time_unit();
48 time_prec_ = up->time_precision();
49 sib_ = up_->sub_;
50 up_->sub_ = this;
51 } else {
52 default_nettype_ = NetNet::NONE;
53 time_unit_ = 0;
54 time_prec_ = 0;
55 assert(t == MODULE);
58 switch (t) {
59 case NetScope::TASK:
60 task_ = 0;
61 break;
62 case NetScope::FUNC:
63 func_ = 0;
64 break;
65 case NetScope::MODULE:
66 module_name_ = perm_string();
67 break;
68 default: /* BEGIN_END and FORK_JOIN, do nothing */
69 break;
71 name_ = n;
74 NetScope::~NetScope()
76 assert(sib_ == 0);
77 assert(sub_ == 0);
78 lcounter_ = 0;
80 /* name_ and module_name_ are perm-allocated. */
83 void NetScope::set_line(const LineInfo*info)
85 file_ = info->get_file();
86 def_file_ = file_;
87 lineno_ = info->get_lineno();
88 def_lineno_ = lineno_;
91 void NetScope::set_line(perm_string file, unsigned lineno)
93 file_ = file;
94 def_file_ = file;
95 lineno_ = lineno;
96 def_lineno_ = lineno;
99 void NetScope::set_line(perm_string file, perm_string def_file,
100 unsigned lineno, unsigned def_lineno)
102 file_ = file;
103 def_file_ = def_file;
104 lineno_ = lineno;
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;
116 ref.expr = expr;
117 ref.type = type;
118 ref.msb = msb;
119 ref.lsb = lsb;
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);
124 return res;
127 bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
129 char tmp[32];
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)) {
137 name_ = new_name;
138 return true;
140 tmp[pad_pos++] = pad;
142 return false;
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)
151 bool flag = false;
153 if (parameters.find(key) != parameters.end()) {
154 param_expr_t&ref = parameters[key];
156 delete ref.expr;
157 ref.expr = expr;
158 flag = true;
161 return flag;
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;
173 ref.expr = expr;
174 ref.msb = 0;
175 ref.lsb = 0;
176 ref.signed_flag = false;
177 ref.set_line(file_line);
178 return res;
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,
189 const NetExpr*&msb,
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;
208 return 0;
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())
216 return idx;
218 idx = localparams.find(perm_string::literal(key));
219 if (idx != localparams.end())
220 return idx;
222 return (map<perm_string,param_expr_t>::iterator) 0;
225 NetScope::TYPE NetScope::type() const
227 return type_;
230 void NetScope::set_task_def(NetTaskDef*def)
232 assert( type_ == TASK );
233 assert( task_ == 0 );
234 task_ = def;
237 NetTaskDef* NetScope::task_def()
239 assert( type_ == TASK );
240 return task_;
243 const NetTaskDef* NetScope::task_def() const
245 assert( type_ == TASK );
246 return task_;
249 void NetScope::set_func_def(NetFuncDef*def)
251 assert( type_ == FUNC );
252 assert( func_ == 0 );
253 func_ = def;
256 NetFuncDef* NetScope::func_def()
258 assert( type_ == FUNC );
259 return func_;
261 bool NetScope::in_func()
263 return (type_ == FUNC) ? true : false;
266 const NetFuncDef* NetScope::func_def() const
268 assert( type_ == FUNC );
269 return 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);
281 return module_name_;
284 void NetScope::time_unit(int val)
286 time_unit_ = val;
289 void NetScope::time_precision(int val)
291 time_prec_ = val;
294 int NetScope::time_unit() const
296 return time_unit_;
299 int NetScope::time_precision() const
301 return time_prec_;
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);
322 ev->scope_ = this;
323 ev->snext_ = events_;
324 events_ = ev;
327 void NetScope::rem_event(NetEvent*ev)
329 assert(ev->scope_ == this);
330 ev->scope_ = 0;
331 if (events_ == ev) {
332 events_ = ev->snext_;
334 } else {
335 NetEvent*cur = events_;
336 while (cur->snext_ != ev) {
337 assert(cur->snext_);
338 cur = cur->snext_;
340 cur->snext_ = ev->snext_;
343 ev->snext_ = 0;
347 NetEvent* NetScope::find_event(perm_string name)
349 for (NetEvent*cur = events_; cur ; cur = cur->snext_)
350 if (cur->name() == name)
351 return cur;
353 return 0;
356 void NetScope::add_signal(NetNet*net)
358 if (signals_ == 0) {
359 net->sig_next_ = net;
360 net->sig_prev_ = net;
361 } else {
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;
367 signals_ = net;
370 void NetScope::rem_signal(NetNet*net)
372 assert(net->scope() == this);
373 if (signals_ == net)
374 signals_ = net->sig_prev_;
376 if (signals_ == net) {
377 signals_ = 0;
378 } else {
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
387 * searched.
389 NetNet* NetScope::find_signal(perm_string key)
391 if (signals_ == 0)
392 return 0;
394 NetNet*cur = signals_;
395 do {
396 if (cur->name() == key)
397 return cur;
398 cur = cur->sig_prev_;
399 } while (cur != signals_);
400 return 0;
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;
411 NetScope*cur = sub_;
412 while (cur->name_ != name) {
413 if (cur->sib_ == 0) return 0;
414 cur = cur->sib_;
417 return cur;
420 const NetScope* NetScope::child(const hname_t&name) const
422 if (sub_ == 0) return 0;
424 NetScope*cur = sub_;
425 while (cur->name_ != name) {
426 if (cur->sib_ == 0) return 0;
427 cur = cur->sib_;
430 return cur;
433 NetScope* NetScope::parent()
435 return up_;
438 const NetScope* NetScope::parent() const
440 return up_;
443 perm_string NetScope::local_symbol()
445 ostringstream res;
446 res << "_s" << (lcounter_++);
447 return lex_strings.make(res.str());
449 #if 0
450 string NetScope::local_hsymbol()
452 return string(name()) + "." + string(local_symbol());
454 #endif