Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 442 lines (354 sloc) 12.725 kb
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
1 /*
2 * Copyright (c) 2012 Stephen Williams (steve@icarus.com)
3 *
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.
9 *
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.
14 *
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
f5aafc3 @arunpersaud updated FSF-address
arunpersaud authored
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
18 */
19
20 # include "netlist.h"
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
21 # include "netmisc.h"
a5a7050 @steveicarus More expression types work in constant functions.
authored
22 # include "compiler.h"
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
23 # include <typeinfo>
24 # include "ivl_assert.h"
25
26 using namespace std;
27
28 NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<NetExpr*>&args) const
29 {
30 // Make the context map;
31 map<perm_string,NetExpr*>::iterator ptr;
32 map<perm_string,NetExpr*>context_map;
33
a5a7050 @steveicarus More expression types work in constant functions.
authored
34 if (debug_eval_tree) {
35 cerr << loc.get_fileline() << ": debug: "
36 << "Evaluate function " << scope_->basename() << endl;
37 }
38
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
39 // Put the return value into the map...
40 context_map[scope_->basename()] = 0;
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
41
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
42 // Load the input ports into the map...
43 ivl_assert(loc, ports_.size() == args.size());
44 for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
45 perm_string aname = ports_[idx]->name();
3354d83 Support if statements and function calls in constant functions.
Martin Whitaker authored
46 context_map[aname] = args[idx];
a5a7050 @steveicarus More expression types work in constant functions.
authored
47
48 if (debug_eval_tree) {
49 cerr << loc.get_fileline() << ": debug: "
3354d83 Support if statements and function calls in constant functions.
Martin Whitaker authored
50 << " input " << aname << " = " << *args[idx] << endl;
a5a7050 @steveicarus More expression types work in constant functions.
authored
51 }
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
52 }
53
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
54 // Ask the scope to collect definitions for local values. This
55 // fills in the context_map with local variables held by the scope.
56 scope_->evaluate_function_find_locals(loc, context_map);
57
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
58 // Perform the evaluation
59 bool flag = statement_->evaluate_function(loc, context_map);
60
61 // Extract the result...
62 ptr = context_map.find(scope_->basename());
63 NetExpr*res = ptr->second;
64 context_map.erase(ptr);
65
66
67 // Cleanup the rest of the context.
68 for (ptr = context_map.begin() ; ptr != context_map.end() ; ++ptr) {
69 delete ptr->second;
70 }
71
72 // Done.
73 if (flag)
74 return res;
75
76 delete res;
77 return 0;
78 }
79
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
80 void NetScope::evaluate_function_find_locals(const LineInfo&loc,
81 map<perm_string,NetExpr*>&context_map) const
82 {
83 for (map<perm_string,NetNet*>::const_iterator cur = signals_map_.begin()
84 ; cur != signals_map_.end() ; ++cur) {
85
86 const NetNet*tmp = cur->second;
87 // Skip ports, which are handled elsewhere.
88 if (tmp->port_type() != NetNet::NOT_A_PORT)
89 continue;
90
91 context_map[tmp->name()] = 0;
92
93 if (debug_eval_tree) {
94 cerr << loc.get_fileline() << ": debug: "
95 << " (local) " << tmp->name() << endl;
96 }
97 }
98 }
99
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
100 NetExpr* NetExpr::evaluate_function(const LineInfo&,
101 map<perm_string,NetExpr*>&) const
102 {
103 cerr << get_fileline() << ": sorry: I don't know how to evaluate this expression at compile time." << endl;
104 cerr << get_fileline() << ": : Expression type:" << typeid(*this).name() << endl;
105
106 return 0;
107 }
108
109 bool NetProc::evaluate_function(const LineInfo&,
110 map<perm_string,NetExpr*>&) const
111 {
112 cerr << get_fileline() << ": sorry: I don't know how to evaluate this statement at compile time." << endl;
113 cerr << get_fileline() << ": : Statement type:" << typeid(*this).name() << endl;
114
115 return false;
116 }
117
118 bool NetAssign::evaluate_function(const LineInfo&loc,
119 map<perm_string,NetExpr*>&context_map) const
120 {
121 if (l_val_count() != 1) {
122 cerr << get_fileline() << ": sorry: I don't know how to evaluate "
123 "concatenated l-values here." << endl;
124 return false;
125 }
126
127 const NetAssign_*lval = l_val(0);
128
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
129 map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
130 ivl_assert(*this, ptr != context_map.end());
131
132 // Do not support having l-values that are unpacked arrays.
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
133 ivl_assert(loc, lval->word() == 0);
134
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
135 // Evaluate the r-value expression.
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
136 NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
137 if (rval_result == 0)
138 return false;
139
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
140 if (const NetExpr*base_expr = lval->get_base()) {
141 NetExpr*base_result = base_expr->evaluate_function(loc, context_map);
142 if (base_result == 0) {
143 delete rval_result;
144 return false;
145 }
146
147 NetEConst*base_const = dynamic_cast<NetEConst*>(base_result);
148 ivl_assert(loc, base_const);
149
150 long base = base_const->value().as_long();
151
152 list<long>prefix (0);
153 base = lval->sig()->sb_to_idx(prefix, base);
154
155 if (ptr->second == 0)
156 ptr->second = make_const_x(lval->sig()->vector_width());
157
158 ivl_assert(loc, base + lval->lwidth() <= ptr->second->expr_width());
159
160 NetEConst*ptr_const = dynamic_cast<NetEConst*>(ptr->second);
161 verinum lval_v = ptr_const->value();
162 NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
163 verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
164
165 for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
166 lval_v.set(idx+base, rval_v[idx]);
167
168 delete base_result;
169 delete rval_result;
170 rval_result = new NetEConst(lval_v);
171 }
172
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
173 if (ptr->second)
174 delete ptr->second;
a5a7050 @steveicarus More expression types work in constant functions.
authored
175
176 if (debug_eval_tree) {
177 cerr << get_fileline() << ": debug: "
178 << "NetAssign::evaluate_function: " << lval->name()
179 << " = " << *rval_result << endl;
180 }
181
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
182 ptr->second = rval_result;
183
184 return true;
185 }
186
187 /*
188 * Evaluating a NetBlock in a function is a simple matter of
189 * evaluating the statements in order.
190 */
191 bool NetBlock::evaluate_function(const LineInfo&loc,
192 map<perm_string,NetExpr*>&context_map) const
193 {
194 bool flag = true;
195 NetProc*cur = last_;
196 do {
197 cur = cur->next_;
198 bool cur_flag = cur->evaluate_function(loc, context_map);
199 flag = flag && cur_flag;
200 } while (cur != last_);
201
202 return flag;
203 }
204
3354d83 Support if statements and function calls in constant functions.
Martin Whitaker authored
205 bool NetCondit::evaluate_function(const LineInfo&loc,
206 map<perm_string,NetExpr*>&context_map) const
207 {
208 NetExpr*cond = expr_->evaluate_function(loc, context_map);
209 if (cond == 0)
210 return false;
211
212 NetEConst*cond_const = dynamic_cast<NetEConst*> (cond);
213 ivl_assert(loc, cond_const);
214
215 long val = cond_const->value().as_long();
216 delete cond;
217
218 if (val)
219 // The condition is true, so evaluate the if clause
220 return (if_ == 0) || if_->evaluate_function(loc, context_map);
221 else
222 // The condition is false, so evaluate the else clause
223 return (else_ == 0) || else_->evaluate_function(loc, context_map);
224 }
225
a5a7050 @steveicarus More expression types work in constant functions.
authored
226 bool NetWhile::evaluate_function(const LineInfo&loc,
227 map<perm_string,NetExpr*>&context_map) const
228 {
229 bool flag = true;
230
231 if (debug_eval_tree) {
befff82 @ldoolitt Spelling fixes
ldoolitt authored
232 cerr << get_fileline() << ": debug: NetWhile::evaluate_function: "
a5a7050 @steveicarus More expression types work in constant functions.
authored
233 << "Start loop" << endl;
234 }
235
236 while (flag) {
237 // Evaluate the condition expression to try and get the
238 // condition for the loop.
239 NetExpr*cond = cond_->evaluate_function(loc, context_map);
240 if (cond == 0) {
241 flag = false;
242 break;
243 }
244
245 NetEConst*cond_const = dynamic_cast<NetEConst*> (cond);
246 ivl_assert(loc, cond_const);
247
248 long val = cond_const->value().as_long();
249 delete cond;
250
251 // If the condition is false, then break.
252 if (val == 0)
253 break;
254
befff82 @ldoolitt Spelling fixes
ldoolitt authored
255 // The condition is true, so evaluate the statement
a5a7050 @steveicarus More expression types work in constant functions.
authored
256 // another time.
257 bool tmp_flag = proc_->evaluate_function(loc, context_map);
258 if (! tmp_flag)
259 flag = false;
260 }
261
262 if (debug_eval_tree) {
befff82 @ldoolitt Spelling fixes
ldoolitt authored
263 cerr << get_fileline() << ": debug: NetWhile::evaluate_function: "
a5a7050 @steveicarus More expression types work in constant functions.
authored
264 << "Done loop" << endl;
265 }
266
267 return flag;
268 }
269
270 NetExpr* NetEBComp::evaluate_function(const LineInfo&loc,
271 map<perm_string,NetExpr*>&context_map) const
272 {
273 NetExpr*lval = left_->evaluate_function(loc, context_map);
274 NetExpr*rval = right_->evaluate_function(loc, context_map);
275
276 if (lval == 0 || rval == 0) {
277 delete lval;
278 delete rval;
279 return 0;
280 }
281
282 NetEConst*res = eval_arguments_(lval, rval);
283 delete lval;
284 delete rval;
285 return res;
286 }
287
288 NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc,
289 map<perm_string,NetExpr*>&context_map) const
290 {
291 NetExpr*lval = left_->evaluate_function(loc, context_map);
292 NetExpr*rval = right_->evaluate_function(loc, context_map);
293
294 if (lval == 0 || rval == 0) {
295 delete lval;
296 delete rval;
297 return 0;
298 }
299
300 NetExpr*res = eval_arguments_(lval, rval);
301 delete lval;
302 delete rval;
303 return res;
304 }
305
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
306 NetExpr* NetEBMult::evaluate_function(const LineInfo&loc,
307 map<perm_string,NetExpr*>&context_map) const
308 {
309 NetExpr*lval = left_->evaluate_function(loc, context_map);
310 NetExpr*rval = right_->evaluate_function(loc, context_map);
311
312 if (lval == 0 || rval == 0) {
313 delete lval;
314 delete rval;
315 return 0;
316 }
317
318 NetExpr*res = eval_arguments_(lval, rval);
319 delete lval;
320 delete rval;
321 return res;
322 }
323
a5a7050 @steveicarus More expression types work in constant functions.
authored
324 NetExpr* NetEBShift::evaluate_function(const LineInfo&loc,
325 map<perm_string,NetExpr*>&context_map) const
326 {
327 NetExpr*lval = left_->evaluate_function(loc, context_map);
328 NetExpr*rval = right_->evaluate_function(loc, context_map);
329
330 if (lval == 0 || rval == 0) {
331 delete lval;
332 delete rval;
333 return 0;
334 }
335
336 NetEConst*res = eval_arguments_(lval, rval);
337 delete lval;
338 delete rval;
339 return res;
340 }
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
341
342 NetExpr* NetEConst::evaluate_function(const LineInfo&,
343 map<perm_string,NetExpr*>&) const
344 {
345 NetEConst*res = new NetEConst(value_);
346 res->set_line(*this);
347 return res;
348 }
a5a7050 @steveicarus More expression types work in constant functions.
authored
349
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
350 NetExpr* NetESelect::evaluate_function(const LineInfo&loc,
351 map<perm_string,NetExpr*>&context_map) const
352 {
353 NetExpr*sub_exp = expr_->evaluate_function(loc, context_map);
354 ivl_assert(loc, sub_exp);
355
356 NetEConst*sub_const = dynamic_cast<NetEConst*> (sub_exp);
357 ivl_assert(loc, sub_exp);
358
359 verinum sub = sub_const->value();
360 delete sub_exp;
361
362 long base = 0;
363 if (base_) {
364 NetExpr*base_val = base_->evaluate_function(loc, context_map);
365 ivl_assert(loc, base_val);
366
367 NetEConst*base_const = dynamic_cast<NetEConst*>(base_val);
368 ivl_assert(loc, base_const);
369
370 base = base_const->value().as_long();
371 delete base_val;
372 } else {
373 sub = pad_to_width(sub, expr_width());
374 }
375
376 verinum res (verinum::Vx, expr_width());
377 for (unsigned idx = 0 ; idx < res.len() ; idx += 1)
378 res.set(idx, sub[base+idx]);
379
380 NetEConst*res_const = new NetEConst(res);
381 return res_const;
382 }
383
a5a7050 @steveicarus More expression types work in constant functions.
authored
384 NetExpr* NetESignal::evaluate_function(const LineInfo&,
385 map<perm_string,NetExpr*>&context_map) const
386 {
387 if (word_) {
388 cerr << get_fileline() << ": sorry: I don't know how to evaluate signal word selects at compile time." << endl;
389 return 0;
390 }
391
392 map<perm_string,NetExpr*>::iterator ptr = context_map.find(name());
393 if (ptr == context_map.end()) {
394 cerr << get_fileline() << ": error: Cannot evaluate " << name()
395 << " in this context." << endl;
396 return 0;
397 }
398
399 return ptr->second->dup_expr();
400 }
62b67c1 @steveicarus More expression types supported during constant function evaluation.
authored
401
402 NetExpr* NetETernary::evaluate_function(const LineInfo&loc,
403 map<perm_string,NetExpr*>&context_map) const
404 {
405 auto_ptr<NetExpr> cval (cond_->evaluate_function(loc, context_map));
406
407 switch (const_logical(cval.get())) {
408
409 case C_0:
410 return false_val_->evaluate_function(loc, context_map);
411 case C_1:
412 return true_val_->evaluate_function(loc, context_map);
413 case C_X:
414 break;
415 default:
416 cerr << get_fileline() << ": error: Condition expression is not constant here." << endl;
417 return 0;
418 }
419
420 NetExpr*tval = true_val_->evaluate_function(loc, context_map);
421 NetExpr*fval = false_val_->evaluate_function(loc, context_map);
422
423 NetExpr*res = blended_arguments_(tval, fval);
424 delete tval;
425 delete fval;
426 return res;
427 }
3354d83 Support if statements and function calls in constant functions.
Martin Whitaker authored
428
429 NetExpr* NetEUFunc::evaluate_function(const LineInfo&loc,
430 map<perm_string,NetExpr*>&context_map) const
431 {
432 NetFuncDef*def = func_->func_def();
433 ivl_assert(*this, def);
434
435 vector<NetExpr*>args(parms_.size());
436 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1)
437 args[idx] = parms_[idx]->evaluate_function(loc, context_map);
438
439 NetExpr*res = def->evaluate_function(*this, args);
440 return res;
441 }
Something went wrong with that request. Please try again.