2 * Copyright (c) 1998-1999 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
28 # include "compiler.h"
30 verinum
* PExpr::eval_const(Design
*, NetScope
*) const
35 verinum
* PEBinary::eval_const(Design
*des
, NetScope
*scope
) const
37 verinum
*l
= left_
->eval_const(des
, scope
);
39 verinum
*r
= right_
->eval_const(des
, scope
);
48 if (l
->is_defined() && r
->is_defined()) {
49 res
= new verinum(*l
+ *r
);
51 res
= new verinum(verinum::Vx
, l
->len());
56 if (l
->is_defined() && r
->is_defined()) {
57 res
= new verinum(*l
- *r
);
59 res
= new verinum(verinum::Vx
, l
->len());
64 if (l
->is_defined() && r
->is_defined()) {
65 res
= new verinum(*l
* *r
);
67 res
= new verinum(verinum::Vx
, l
->len());
72 if (l
->is_defined() && r
->is_defined()) {
73 long lv
= l
->as_long();
74 long rv
= r
->as_long();
75 res
= new verinum(lv
/ rv
, l
->len());
77 res
= new verinum(verinum::Vx
, l
->len());
82 if (l
->is_defined() && r
->is_defined()) {
83 long lv
= l
->as_long();
84 long rv
= r
->as_long();
85 res
= new verinum(lv
% rv
, l
->len());
87 res
= new verinum(verinum::Vx
, l
->len());
92 if (l
->is_defined() && r
->is_defined()) {
93 long lv
= l
->as_long();
94 long rv
= r
->as_long();
95 res
= new verinum(lv
> rv
, l
->len());
97 res
= new verinum(verinum::Vx
, l
->len());
102 if (l
->is_defined() && r
->is_defined()) {
103 long lv
= l
->as_long();
104 long rv
= r
->as_long();
105 res
= new verinum(lv
< rv
, l
->len());
107 res
= new verinum(verinum::Vx
, l
->len());
111 case 'l': { // left shift (<<)
112 assert(r
->is_defined());
113 unsigned long rv
= r
->as_ulong();
114 res
= new verinum(verinum::V0
, l
->len());
115 if (rv
< res
->len()) {
116 unsigned cnt
= res
->len() - rv
;
117 for (unsigned idx
= 0 ; idx
< cnt
; idx
+= 1)
118 res
->set(idx
+rv
, l
->get(idx
));
122 case 'r': { // right shift (>>)
123 assert(r
->is_defined());
124 unsigned long rv
= r
->as_ulong();
125 res
= new verinum(verinum::V0
, l
->len());
126 if (rv
< res
->len()) {
127 unsigned cnt
= res
->len() - rv
;
128 for (unsigned idx
= 0 ; idx
< cnt
; idx
+= 1)
129 res
->set(idx
, l
->get(idx
+rv
));
144 verinum
* PEConcat::eval_const(Design
*des
, NetScope
*scope
) const
146 verinum
*accum
= parms_
[0]->eval_const(des
, scope
);
150 for (unsigned idx
= 1 ; idx
< parms_
.count() ; idx
+= 1) {
152 verinum
*tmp
= parms_
[idx
]->eval_const(des
, scope
);
159 *accum
= concat(*accum
, *tmp
);
168 * Evaluate an identifier as a constant expression. This is only
169 * possible if the identifier is that of a parameter.
171 verinum
* PEIdent::eval_const(Design
*des
, NetScope
*scope
) const
178 const name_component_t
&name_tail
= path_
.back();
180 // Handle the special case that this ident is a genvar
181 // variable name. In that case, the genvar meaning preempts
182 // everything and we just return that value immediately.
183 if (scope
->genvar_tmp
184 && strcmp(name_tail
.name
,scope
->genvar_tmp
) == 0) {
185 return new verinum(scope
->genvar_tmp_val
);
188 symbol_search(des
, scope
, path_
, net
, expr
, eve
);
193 const NetEConst
*eval
= dynamic_cast<const NetEConst
*>(expr
);
195 cerr
<< get_fileline() << ": internal error: Unable to evaluate "
196 << "constant expression (parameter=" << path_
197 << "): " << *expr
<< endl
;
203 if (!name_tail
.index
.empty())
207 return new verinum(eval
->value());
210 verinum
* PEFNumber::eval_const(Design
*, NetScope
*) const
212 long val
= value_
->as_long();
213 return new verinum(val
);
216 verinum
* PENumber::eval_const(Design
*, NetScope
*) const
218 return new verinum(value());
221 verinum
* PEString::eval_const(Design
*, NetScope
*) const
223 return new verinum(string(text_
));
226 verinum
* PETernary::eval_const(Design
*des
, NetScope
*scope
) const
228 verinum
*test
= expr_
->eval_const(des
, scope
);
232 verinum::V bit
= test
->get(0);
236 return fal_
->eval_const(des
, scope
);
238 return tru_
->eval_const(des
, scope
);
241 // XXXX It is possible to handle this case if both fal_
242 // and tru_ are constant. Someday...
246 verinum
* PEUnary::eval_const(Design
*des
, NetScope
*scope
) const
248 verinum
*val
= expr_
->eval_const(des
, scope
);
257 /* We need to expand the value a bit if we are
258 taking the 2's complement so that we are
259 guaranteed to not overflow. */
260 verinum
tmp ((uint64_t)0, val
->len()+1);
261 for (unsigned idx
= 0 ; idx
< val
->len() ; idx
+= 1)
262 tmp
.set(idx
, val
->get(idx
));
264 *val
= v_not(tmp
) + verinum(verinum::V1
, 1);