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)
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 #ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
26 # include "compiler.h"
31 # include "ivl_assert.h"
33 NetExpr
*PExpr::elaborate_pexpr(Design
*des
, NetScope
*sc
) const
35 cerr
<< get_line() << ": error: invalid parameter expression: "
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
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)) {
58 NetEBinary
*tmp
= elaborate_expr_base_(des
, lp
, rp
, -2);
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
70 NetEConcat
* PEConcat::elaborate_pexpr(Design
*des
, NetScope
*scope
) const
74 /* If there is a repeat expression, then evaluate the constant
75 value and set the repeat count. */
77 repeat
= repeat_
->elaborate_pexpr(des
, scope
);
79 cerr
<< get_line() << ": error: "
80 "concatenation repeat expression cannot be evaluated."
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
);
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) {
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: "
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();
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.
152 ex
= pscope
->get_parameter(name_tail
.name
, ex_msb
, ex_lsb
);
155 if (pscope
->type() == NetScope::MODULE
)
157 pscope
= pscope
->parent();
158 ivl_assert(*this, pscope
);
161 cerr
<< get_line() << ": error: identifier ``" << name_tail
.name
<<
162 "'' is not a parameter in "<< scope_path(scope
)<< "." << endl
;
167 NetExpr
*res
= new NetEParam(des
, pscope
, name_tail
.name
);
168 res
->set_line(*this);
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
;
176 case index_component_t::SEL_NONE
:
179 case index_component_t::SEL_PART
:
180 cerr
<< get_line() << ": sorry: Cannot part select "
181 "bits of parameters." << endl
;
185 case index_component_t::SEL_BIT
:
187 /* We have here a bit select. Insert a NetESelect node
189 NetExpr
*tmp
= name_tail
.index
.back().msb
->elaborate_pexpr(des
, scope
);
191 res
= new NetESelect(res
, tmp
, 1);
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() ?
236 tmp
= new NetEUnary(op_
, ip
);
237 tmp
->set_line(*this);
240 tmp
= new NetEUBits(op_
, ip
);
241 tmp
->set_line(*this);
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);