Skip to content
Newer
Older
100644 267 lines (218 sloc) 7.31 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
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 */
19
20 # include "netlist.h"
a5a7050 @steveicarus More expression types work in constant functions.
authored
21 # include "compiler.h"
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
22 # include <typeinfo>
23 # include "ivl_assert.h"
24
25 using namespace std;
26
27 NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<NetExpr*>&args) const
28 {
29 // Make the context map;
30 map<perm_string,NetExpr*>::iterator ptr;
31 map<perm_string,NetExpr*>context_map;
32
a5a7050 @steveicarus More expression types work in constant functions.
authored
33 if (debug_eval_tree) {
34 cerr << loc.get_fileline() << ": debug: "
35 << "Evaluate function " << scope_->basename() << endl;
36 }
37
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
38 // Put the return value into the map...
39 context_map[scope_->basename()] = 0;
40 // Load the input ports into the map...
41 ivl_assert(loc, ports_.size() == args.size());
42 for (size_t idx = 0 ; idx < ports_.size() ; idx += 1) {
43 NetExpr*tmp = args[idx]->dup_expr();
44 perm_string aname = ports_[idx]->name();
45 context_map[aname] = tmp;
a5a7050 @steveicarus More expression types work in constant functions.
authored
46
47 if (debug_eval_tree) {
48 cerr << loc.get_fileline() << ": debug: "
49 << " input " << aname << " = " << *tmp << endl;
50 }
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
51 }
52
53 // Perform the evaluation
54 bool flag = statement_->evaluate_function(loc, context_map);
55
56 // Extract the result...
57 ptr = context_map.find(scope_->basename());
58 NetExpr*res = ptr->second;
59 context_map.erase(ptr);
60
61
62 // Cleanup the rest of the context.
63 for (ptr = context_map.begin() ; ptr != context_map.end() ; ++ptr) {
64 delete ptr->second;
65 }
66
67 // Done.
68 if (flag)
69 return res;
70
71 delete res;
72 return 0;
73 }
74
75 NetExpr* NetExpr::evaluate_function(const LineInfo&,
76 map<perm_string,NetExpr*>&) const
77 {
78 cerr << get_fileline() << ": sorry: I don't know how to evaluate this expression at compile time." << endl;
79 cerr << get_fileline() << ": : Expression type:" << typeid(*this).name() << endl;
80
81 return 0;
82 }
83
84 bool NetProc::evaluate_function(const LineInfo&,
85 map<perm_string,NetExpr*>&) const
86 {
87 cerr << get_fileline() << ": sorry: I don't know how to evaluate this statement at compile time." << endl;
88 cerr << get_fileline() << ": : Statement type:" << typeid(*this).name() << endl;
89
90 return false;
91 }
92
93 bool NetAssign::evaluate_function(const LineInfo&loc,
94 map<perm_string,NetExpr*>&context_map) const
95 {
96 if (l_val_count() != 1) {
97 cerr << get_fileline() << ": sorry: I don't know how to evaluate "
98 "concatenated l-values here." << endl;
99 return false;
100 }
101
102 const NetAssign_*lval = l_val(0);
103
104 ivl_assert(loc, lval->word() == 0);
105 ivl_assert(loc, lval->get_base() == 0);
106
107 NetExpr*rval_result = rval()->evaluate_function(loc, context_map);
108 if (rval_result == 0)
109 return false;
110
111 map<perm_string,NetExpr*>::iterator ptr = context_map.find(lval->name());
112 if (ptr->second)
113 delete ptr->second;
a5a7050 @steveicarus More expression types work in constant functions.
authored
114
115 if (debug_eval_tree) {
116 cerr << get_fileline() << ": debug: "
117 << "NetAssign::evaluate_function: " << lval->name()
118 << " = " << *rval_result << endl;
119 }
120
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
121 ptr->second = rval_result;
122
123 return true;
124 }
125
126 /*
127 * Evaluating a NetBlock in a function is a simple matter of
128 * evaluating the statements in order.
129 */
130 bool NetBlock::evaluate_function(const LineInfo&loc,
131 map<perm_string,NetExpr*>&context_map) const
132 {
133 bool flag = true;
134 NetProc*cur = last_;
135 do {
136 cur = cur->next_;
137 bool cur_flag = cur->evaluate_function(loc, context_map);
138 flag = flag && cur_flag;
139 } while (cur != last_);
140
141 return flag;
142 }
143
a5a7050 @steveicarus More expression types work in constant functions.
authored
144 bool NetWhile::evaluate_function(const LineInfo&loc,
145 map<perm_string,NetExpr*>&context_map) const
146 {
147 bool flag = true;
148
149 if (debug_eval_tree) {
150 cerr << get_fileline() << ": debug: NetWhile::evaluate_fuction: "
151 << "Start loop" << endl;
152 }
153
154 while (flag) {
155 // Evaluate the condition expression to try and get the
156 // condition for the loop.
157 NetExpr*cond = cond_->evaluate_function(loc, context_map);
158 if (cond == 0) {
159 flag = false;
160 break;
161 }
162
163 NetEConst*cond_const = dynamic_cast<NetEConst*> (cond);
164 ivl_assert(loc, cond_const);
165
166 long val = cond_const->value().as_long();
167 delete cond;
168
169 // If the condition is false, then break.
170 if (val == 0)
171 break;
172
173 // The condition is true, so evalutate the statement
174 // another time.
175 bool tmp_flag = proc_->evaluate_function(loc, context_map);
176 if (! tmp_flag)
177 flag = false;
178 }
179
180 if (debug_eval_tree) {
181 cerr << get_fileline() << ": debug: NetWhile::evaluate_fuction: "
182 << "Done loop" << endl;
183 }
184
185 return flag;
186 }
187
188 NetExpr* NetEBComp::evaluate_function(const LineInfo&loc,
189 map<perm_string,NetExpr*>&context_map) const
190 {
191 NetExpr*lval = left_->evaluate_function(loc, context_map);
192 NetExpr*rval = right_->evaluate_function(loc, context_map);
193
194 if (lval == 0 || rval == 0) {
195 delete lval;
196 delete rval;
197 return 0;
198 }
199
200 NetEConst*res = eval_arguments_(lval, rval);
201 delete lval;
202 delete rval;
203 return res;
204 }
205
206 NetExpr* NetEBAdd::evaluate_function(const LineInfo&loc,
207 map<perm_string,NetExpr*>&context_map) const
208 {
209 NetExpr*lval = left_->evaluate_function(loc, context_map);
210 NetExpr*rval = right_->evaluate_function(loc, context_map);
211
212 if (lval == 0 || rval == 0) {
213 delete lval;
214 delete rval;
215 return 0;
216 }
217
218 NetExpr*res = eval_arguments_(lval, rval);
219 delete lval;
220 delete rval;
221 return res;
222 }
223
224 NetExpr* NetEBShift::evaluate_function(const LineInfo&loc,
225 map<perm_string,NetExpr*>&context_map) const
226 {
227 NetExpr*lval = left_->evaluate_function(loc, context_map);
228 NetExpr*rval = right_->evaluate_function(loc, context_map);
229
230 if (lval == 0 || rval == 0) {
231 delete lval;
232 delete rval;
233 return 0;
234 }
235
236 NetEConst*res = eval_arguments_(lval, rval);
237 delete lval;
238 delete rval;
239 return res;
240 }
def9d0e @steveicarus Basic infrastructure for compile-time function evaluation.
authored
241
242 NetExpr* NetEConst::evaluate_function(const LineInfo&,
243 map<perm_string,NetExpr*>&) const
244 {
245 NetEConst*res = new NetEConst(value_);
246 res->set_line(*this);
247 return res;
248 }
a5a7050 @steveicarus More expression types work in constant functions.
authored
249
250 NetExpr* NetESignal::evaluate_function(const LineInfo&,
251 map<perm_string,NetExpr*>&context_map) const
252 {
253 if (word_) {
254 cerr << get_fileline() << ": sorry: I don't know how to evaluate signal word selects at compile time." << endl;
255 return 0;
256 }
257
258 map<perm_string,NetExpr*>::iterator ptr = context_map.find(name());
259 if (ptr == context_map.end()) {
260 cerr << get_fileline() << ": error: Cannot evaluate " << name()
261 << " in this context." << endl;
262 return 0;
263 }
264
265 return ptr->second->dup_expr();
266 }
Something went wrong with that request. Please try again.