Add -D to iverilog-vpi and update documentation.
[iverilog.git] / elab_pexpr.cc
blob140f1cc016f55ba75a926ebfcc12ad196b8f66f7
1 /*
2 * Copyright (c) 2000-2007 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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
21 #endif
23 # include "config.h"
25 # include "PExpr.h"
26 # include "compiler.h"
27 # include "util.h"
28 # include "netmisc.h"
30 # include <iostream>
31 # include "ivl_assert.h"
33 NetExpr*PExpr::elaborate_pexpr(Design*des, NetScope*sc) const
35 cerr << get_line() << ": error: invalid parameter expression: "
36 << *this << endl;
37 des->errors += 1;
39 return 0;
43 * Binary operators have sub-expressions that must be elaborated as
44 * parameter expressions. If either of them fail, then give up. Once
45 * they are taken care of, make the base object just as in any other
46 * expression.
48 NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
50 NetExpr*lp = left_->elaborate_pexpr(des, scope);
51 NetExpr*rp = right_->elaborate_pexpr(des, scope);
52 if ((lp == 0) || (rp == 0)) {
53 delete lp;
54 delete rp;
55 return 0;
58 NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -2);
59 return tmp;
63 * Event though parameters are not generally sized, parameter
64 * expressions can include concatenation expressions. This requires
65 * that the subexpressions all have well-defined size (in spite of
66 * being in a parameter expression) in order to get a defined
67 * value. The sub-expressions themselves must also be value parameter
68 * expressions.
70 NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
72 NetExpr* repeat = 0;
74 /* If there is a repeat expression, then evaluate the constant
75 value and set the repeat count. */
76 if (repeat_) {
77 repeat = repeat_->elaborate_pexpr(des, scope);
78 if (repeat == 0) {
79 cerr << get_line() << ": error: "
80 "concatenation repeat expression cannot be evaluated."
81 << endl;
82 des->errors += 1;
85 /* continue on even if the repeat expression doesn't
86 work, as we can find more errors. */
89 /* Make the empty concat expression. */
90 NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
91 tmp->set_line(*this);
93 /* Elaborate all the operands and attach them to the concat
94 node. Use the elaborate_pexpr method instead of the
95 elaborate_expr method. */
96 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
97 assert(parms_[idx]);
98 NetExpr*ex = parms_[idx]->elaborate_pexpr(des, scope);
99 if (ex == 0) continue;
101 ex->set_line(*parms_[idx]);
103 if (dynamic_cast<NetEParam*>(ex)) {
105 /* If this parameter is a NetEParam, then put off
106 the width check for later. */
108 } else if (! ex->has_width()) {
109 cerr << ex->get_line() << ": error: operand of "
110 << "concatenation has indefinite width: "
111 << *ex << endl;
112 des->errors += 1;
116 tmp->set(idx, ex);
119 return tmp;
122 NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
124 return elaborate_expr(des, scope, -1, false);
128 * Parameter expressions may reference other parameters, but only in
129 * the current scope. Preserve the parameter reference in the
130 * parameter expression I'm generating, instead of evaluating it now,
131 * because the referenced parameter may yet be overridden.
133 NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
135 pform_name_t path = path_;
136 name_component_t name_tail = path_.back();
137 path.pop_back();
139 NetScope*pscope = scope;
140 if (path_.size() > 0) {
141 list<hname_t> tmp = eval_scope_path(des, scope, path);
142 pscope = des->find_scope(scope, tmp);
145 const NetExpr*ex_msb;
146 const NetExpr*ex_lsb;
147 const NetExpr*ex = 0;
148 // Look up the parameter name in the current scope. If the
149 // name is not found in the pscope, look in containing scopes,
150 // but do not go outside the containing module instance.
151 for (;;) {
152 ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
153 if (ex != 0)
154 break;
155 if (pscope->type() == NetScope::MODULE)
156 break;
157 pscope = pscope->parent();
158 ivl_assert(*this, pscope);
160 if (ex == 0) {
161 cerr << get_line() << ": error: identifier ``" << name_tail.name <<
162 "'' is not a parameter in "<< scope_path(scope)<< "." << endl;
163 des->errors += 1;
164 return 0;
167 NetExpr*res = new NetEParam(des, pscope, name_tail.name);
168 res->set_line(*this);
169 assert(res);
171 index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
172 if (!name_tail.index.empty())
173 use_sel = name_tail.index.back().sel;
175 switch (use_sel) {
176 case index_component_t::SEL_NONE:
177 break;
178 default:
179 case index_component_t::SEL_PART:
180 cerr << get_line() << ": sorry: Cannot part select "
181 "bits of parameters." << endl;
182 des->errors += 1;
183 break;
185 case index_component_t::SEL_BIT:
187 /* We have here a bit select. Insert a NetESelect node
188 to handle it. */
189 NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
190 if (tmp != 0) {
191 res = new NetESelect(res, tmp, 1);
193 break;
196 return res;
200 * Simple numbers can be elaborated by the elaborate_expr method.
202 NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
204 return elaborate_expr(des, sc, -1, false);
208 NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
210 return elaborate_expr(des, scope, -1, false);
213 NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
215 NetExpr*c = expr_->elaborate_pexpr(des, scope);
216 NetExpr*t = tru_->elaborate_pexpr(des, scope);
217 NetExpr*f = fal_->elaborate_pexpr(des, scope);
218 if (c == 0) return 0;
219 if (t == 0) return 0;
220 if (f == 0) return 0;
221 return new NetETernary(c, t, f);
224 NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
226 NetExpr*ip = expr_->elaborate_pexpr(des, scope);
227 if (ip == 0) return 0;
229 /* Should we evaluate expressions ahead of time,
230 * just like in PEBinary::elaborate_expr() ?
233 NetEUnary*tmp;
234 switch (op_) {
235 default:
236 tmp = new NetEUnary(op_, ip);
237 tmp->set_line(*this);
238 break;
239 case '~':
240 tmp = new NetEUBits(op_, ip);
241 tmp->set_line(*this);
242 break;
243 case '!': // Logical NOT
244 case '&': // Reduction AND
245 case '|': // Reduction OR
246 case '^': // Reduction XOR
247 case 'A': // Reduction NAND (~&)
248 case 'N': // Reduction NOR (~|)
249 case 'X': // Reduction NXOR (~^)
250 tmp = new NetEUReduce(op_, ip);
251 tmp->set_line(*this);
252 break;
254 return tmp;