Add file and line information for parameters, etc.
[sverilog.git] / net_scope.cc
blob01799f1074b1a472d1691f7d450e10ce10980dcd
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 <sstream>
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
33 * in question.
36 NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
37 : type_(t), up_(up), sib_(0), sub_(0)
39 signals_ = 0;
40 events_ = 0;
41 lcounter_ = 0;
43 if (up) {
44 default_nettype_ = up->default_nettype();
45 time_unit_ = up->time_unit();
46 time_prec_ = up->time_precision();
47 sib_ = up_->sub_;
48 up_->sub_ = this;
49 } else {
50 default_nettype_ = NetNet::NONE;
51 time_unit_ = 0;
52 time_prec_ = 0;
53 assert(t == MODULE);
56 switch (t) {
57 case NetScope::TASK:
58 task_ = 0;
59 break;
60 case NetScope::FUNC:
61 func_ = 0;
62 break;
63 case NetScope::MODULE:
64 module_name_ = perm_string();
65 break;
66 default: /* BEGIN_END and FORK_JOIN, do nothing */
67 break;
69 name_ = n;
72 NetScope::~NetScope()
74 assert(sib_ == 0);
75 assert(sub_ == 0);
76 lcounter_ = 0;
78 /* name_ and module_name_ are perm-allocated. */
81 void NetScope::set_line(const LineInfo*info)
83 file_ = info->get_file();
84 def_file_ = file_;
85 lineno_ = info->get_lineno();
86 def_lineno_ = lineno_;
89 void NetScope::set_line(perm_string file, unsigned lineno)
91 file_ = file;
92 def_file_ = file;
93 lineno_ = lineno;
94 def_lineno_ = lineno;
97 void NetScope::set_line(perm_string file, perm_string def_file,
98 unsigned lineno, unsigned def_lineno)
100 file_ = file;
101 def_file_ = def_file;
102 lineno_ = lineno;
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;
112 ref.expr = expr;
113 ref.msb = msb;
114 ref.lsb = lsb;
115 ref.signed_flag = signed_flag;
116 ref.file = file;
117 ref.lineno = lineno;
118 return res;
121 bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
123 char tmp[32];
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)) {
131 name_ = new_name;
132 return true;
134 tmp[pad_pos++] = pad;
136 return false;
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)
145 bool flag = false;
147 if (parameters.find(key) != parameters.end()) {
148 param_expr_t&ref = parameters[key];
150 delete ref.expr;
151 ref.expr = expr;
152 flag = true;
155 return flag;
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;
167 ref.expr = expr;
168 ref.msb = 0;
169 ref.lsb = 0;
170 ref.signed_flag = false;
171 ref.file = file;
172 ref.lineno = lineno;
173 return res;
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,
184 const NetExpr*&msb,
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;
203 return 0;
206 NetScope::TYPE NetScope::type() const
208 return type_;
211 void NetScope::set_task_def(NetTaskDef*def)
213 assert( type_ == TASK );
214 assert( task_ == 0 );
215 task_ = def;
218 NetTaskDef* NetScope::task_def()
220 assert( type_ == TASK );
221 return task_;
224 const NetTaskDef* NetScope::task_def() const
226 assert( type_ == TASK );
227 return task_;
230 void NetScope::set_func_def(NetFuncDef*def)
232 assert( type_ == FUNC );
233 assert( func_ == 0 );
234 func_ = def;
237 NetFuncDef* NetScope::func_def()
239 assert( type_ == FUNC );
240 return func_;
242 bool NetScope::in_func()
244 return (type_ == FUNC) ? true : false;
247 const NetFuncDef* NetScope::func_def() const
249 assert( type_ == FUNC );
250 return 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);
262 return module_name_;
265 void NetScope::time_unit(int val)
267 time_unit_ = val;
270 void NetScope::time_precision(int val)
272 time_prec_ = val;
275 int NetScope::time_unit() const
277 return time_unit_;
280 int NetScope::time_precision() const
282 return time_prec_;
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);
303 ev->scope_ = this;
304 ev->snext_ = events_;
305 events_ = ev;
308 void NetScope::rem_event(NetEvent*ev)
310 assert(ev->scope_ == this);
311 ev->scope_ = 0;
312 if (events_ == ev) {
313 events_ = ev->snext_;
315 } else {
316 NetEvent*cur = events_;
317 while (cur->snext_ != ev) {
318 assert(cur->snext_);
319 cur = cur->snext_;
321 cur->snext_ = ev->snext_;
324 ev->snext_ = 0;
328 NetEvent* NetScope::find_event(perm_string name)
330 for (NetEvent*cur = events_; cur ; cur = cur->snext_)
331 if (cur->name() == name)
332 return cur;
334 return 0;
337 void NetScope::add_signal(NetNet*net)
339 if (signals_ == 0) {
340 net->sig_next_ = net;
341 net->sig_prev_ = net;
342 } else {
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;
348 signals_ = net;
351 void NetScope::rem_signal(NetNet*net)
353 assert(net->scope() == this);
354 if (signals_ == net)
355 signals_ = net->sig_prev_;
357 if (signals_ == net) {
358 signals_ = 0;
359 } else {
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
368 * searched.
370 NetNet* NetScope::find_signal(perm_string key)
372 if (signals_ == 0)
373 return 0;
375 NetNet*cur = signals_;
376 do {
377 if (cur->name() == key)
378 return cur;
379 cur = cur->sig_prev_;
380 } while (cur != signals_);
381 return 0;
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;
392 NetScope*cur = sub_;
393 while (cur->name_ != name) {
394 if (cur->sib_ == 0) return 0;
395 cur = cur->sib_;
398 return cur;
401 const NetScope* NetScope::child(const hname_t&name) const
403 if (sub_ == 0) return 0;
405 NetScope*cur = sub_;
406 while (cur->name_ != name) {
407 if (cur->sib_ == 0) return 0;
408 cur = cur->sib_;
411 return cur;
414 NetScope* NetScope::parent()
416 return up_;
419 const NetScope* NetScope::parent() const
421 return up_;
424 perm_string NetScope::local_symbol()
426 ostringstream res;
427 res << "_s" << (lcounter_++);
428 return lex_strings.make(res.str());
430 #if 0
431 string NetScope::local_hsymbol()
433 return string(name()) + "." + string(local_symbol());
435 #endif