Merge branch 'master' into verilog-ams
[sverilog.git] / t-dll-expr.cc
blob958e5d0f27dedd7afc9aa560d7d4b0b1fadd6539
1 /*
2 * Copyright (c) 2000-2008 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
20 # include "config.h"
22 # include <iostream>
24 # include <cstring>
25 # include "t-dll.h"
26 # include "netlist.h"
27 # include <assert.h>
28 #ifdef HAVE_MALLOC_H
29 # include <malloc.h>
30 #endif
31 # include <stdlib.h>
34 * This is a little convenience function for converting a NetExpr
35 * expression type to the expression type used by ivl_expr_t objects.
37 static ivl_variable_type_t get_expr_type(const NetExpr*net)
39 return net->expr_type();
43 * These methods implement the expression scan that generates the
44 * ivl_expr_t representing the expression. Each method leaves the
45 * expr_ member filled with the ivl_expr_t that represents it. Each
46 * method expects that the expr_ member empty (0) when it starts.
50 * This function takes an expression in the expr_ member that is
51 * already built up, and adds a subtraction of the given constant.
53 void dll_target::sub_off_from_expr_(long off)
55 assert(expr_ != 0);
57 char*bits;
58 ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
59 tmpc->type_ = IVL_EX_NUMBER;
60 tmpc->value_ = IVL_VT_VECTOR;
61 tmpc->width_ = expr_->width_;
62 tmpc->signed_ = expr_->signed_;
63 tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
64 for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
65 bits[idx] = (off & 1)? '1' : '0';
66 off >>= 1;
69 /* Now make the subtractor (x-4 in the above example)
70 that has as input A the index expression and input B
71 the constant to subtract. */
72 ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
73 tmps->type_ = IVL_EX_BINARY;
74 tmps->value_ = IVL_VT_VECTOR;
75 tmps->width_ = tmpc->width_;
76 tmps->signed_ = tmpc->signed_;
77 tmps->u_.binary_.op_ = '-';
78 tmps->u_.binary_.lef_ = expr_;
79 tmps->u_.binary_.rig_ = tmpc;
81 /* Replace (x) with (x-off) */
82 expr_ = tmps;
85 void dll_target::mul_expr_by_const_(long val)
87 assert(expr_ != 0);
89 char*bits;
90 ivl_expr_t tmpc = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
91 tmpc->type_ = IVL_EX_NUMBER;
92 tmpc->value_ = IVL_VT_VECTOR;
93 tmpc->width_ = expr_->width_;
94 tmpc->signed_ = expr_->signed_;
95 tmpc->u_.number_.bits_ = bits = (char*)malloc(tmpc->width_);
96 for (unsigned idx = 0 ; idx < tmpc->width_ ; idx += 1) {
97 bits[idx] = (val & 1)? '1' : '0';
98 val >>= 1;
101 /* Now make the subtractor (x-4 in the above example)
102 that has as input A the index expression and input B
103 the constant to subtract. */
104 ivl_expr_t tmps = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
105 tmps->type_ = IVL_EX_BINARY;
106 tmps->value_ = IVL_VT_VECTOR;
107 tmps->width_ = tmpc->width_;
108 tmps->signed_ = tmpc->signed_;
109 tmps->u_.binary_.op_ = '*';
110 tmps->u_.binary_.lef_ = expr_;
111 tmps->u_.binary_.rig_ = tmpc;
113 /* Replace (x) with (x*valf) */
114 expr_ = tmps;
117 ivl_expr_t dll_target::expr_from_value_(const verinum&val)
119 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
120 assert(expr);
122 unsigned idx;
123 char*bits;
124 expr->type_ = IVL_EX_NUMBER;
125 expr->value_= IVL_VT_VECTOR;
126 expr->width_= val.len();
127 expr->signed_ = val.has_sign()? 1 : 0;
128 expr->u_.number_.bits_ = bits = (char*)malloc(expr->width_ + 1);
129 for (idx = 0 ; idx < expr->width_ ; idx += 1)
130 switch (val.get(idx)) {
131 case verinum::V0:
132 bits[idx] = '0';
133 break;
134 case verinum::V1:
135 bits[idx] = '1';
136 break;
137 case verinum::Vx:
138 bits[idx] = 'x';
139 break;
140 case verinum::Vz:
141 bits[idx] = 'z';
142 break;
143 default:
144 assert(0);
147 bits[expr->width_] = 0;
149 return expr;
152 void dll_target::expr_binary(const NetEBinary*net)
154 assert(expr_ == 0);
156 net->left()->expr_scan(this);
157 ivl_expr_t left = expr_;
159 expr_ = 0;
160 net->right()->expr_scan(this);
161 ivl_expr_t rght = expr_;
163 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
164 assert(expr_);
166 expr_->type_ = IVL_EX_BINARY;
167 expr_->value_= get_expr_type(net);
168 expr_->width_= net->expr_width();
169 expr_->signed_ = net->has_sign()? 1 : 0;
171 expr_->u_.binary_.op_ = net->op();
172 expr_->u_.binary_.lef_ = left;
173 expr_->u_.binary_.rig_ = rght;
176 void dll_target::expr_concat(const NetEConcat*net)
178 assert(expr_ == 0);
180 ivl_expr_t cur = new struct ivl_expr_s;
181 assert(cur);
183 cur->type_ = IVL_EX_CONCAT;
184 cur->value_ = IVL_VT_VECTOR;
185 cur->width_ = net->expr_width();
186 cur->signed_ = 0;
188 cur->u_.concat_.rept = net->repeat();
189 cur->u_.concat_.parms = net->nparms();
190 cur->u_.concat_.parm = new ivl_expr_t [net->nparms()];
192 for (unsigned idx = 0 ; idx < net->nparms() ; idx += 1) {
193 expr_ = 0;
194 net->parm(idx)->expr_scan(this);
195 assert(expr_);
196 cur->u_.concat_.parm[idx] = expr_;
199 expr_ = cur;
202 void dll_target::expr_const(const NetEConst*net)
204 assert(expr_ == 0);
206 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
207 assert(expr_);
208 expr_->value_= net->expr_type();
210 if (net->value().is_string()) {
211 expr_->type_ = IVL_EX_STRING;
212 expr_->width_= net->expr_width();
213 expr_->u_.string_.value_ =strdup(net->value().as_string().c_str());
215 } else {
216 verinum val = net->value();
217 unsigned idx;
218 char*bits;
219 expr_->type_ = IVL_EX_NUMBER;
220 expr_->width_= net->expr_width();
221 expr_->signed_ = net->has_sign()? 1 : 0;
222 expr_->u_.number_.bits_ = bits = (char*)malloc(expr_->width_);
223 for (idx = 0 ; idx < expr_->width_ ; idx += 1)
224 switch (val.get(idx)) {
225 case verinum::V0:
226 bits[idx] = '0';
227 break;
228 case verinum::V1:
229 bits[idx] = '1';
230 break;
231 case verinum::Vx:
232 bits[idx] = 'x';
233 break;
234 case verinum::Vz:
235 bits[idx] = 'z';
236 break;
237 default:
238 assert(0);
244 void dll_target::expr_param(const NetEConstParam*net)
246 ivl_scope_t scope = find_scope(des_, net->scope());
247 ivl_parameter_t par = scope_find_param(scope, net->name());
249 if (par == 0) {
250 cerr << net->get_fileline() << ": internal error: "
251 << "Parameter " << net->name() << " missing from "
252 << ivl_scope_name(scope) << endl;
254 assert(par);
255 assert(par->value);
256 expr_ = par->value;
259 void dll_target::expr_creal(const NetECReal*net)
261 assert(expr_ == 0);
262 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
263 expr_->width_ = net->expr_width();
264 expr_->signed_ = 1;
265 expr_->type_ = IVL_EX_REALNUM;
266 expr_->value_= IVL_VT_REAL;
267 expr_->u_.real_.value = net->value().as_double();
270 void dll_target::expr_event(const NetEEvent*net)
272 assert(expr_ == 0);
274 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
275 assert(expr_);
277 expr_->type_ = IVL_EX_EVENT;
278 expr_->value_= IVL_VT_VOID;
280 /* Locate the event by name. Save the ivl_event_t in the
281 expression so that the generator can find it easily. */
282 const NetEvent*ev = net->event();
283 ivl_scope_t ev_scope = lookup_scope_(ev->scope());
285 for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
286 const char*ename = ivl_event_basename(ev_scope->event_[idx]);
287 if (strcmp(ev->name(), ename) == 0) {
288 expr_->u_.event_.event = ev_scope->event_[idx];
289 break;
294 void dll_target::expr_scope(const NetEScope*net)
296 assert(expr_ == 0);
298 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
299 assert(expr_);
301 expr_->type_ = IVL_EX_SCOPE;
302 expr_->value_= IVL_VT_VOID;
303 expr_->u_.scope_.scope = lookup_scope_(net->scope());
306 void dll_target::expr_select(const NetESelect*net)
308 assert(expr_ == 0);
310 net->sub_expr()->expr_scan(this);
311 ivl_expr_t left = expr_;
313 expr_ = 0;
314 if (net->select())
315 net->select()->expr_scan(this);
317 ivl_expr_t rght = expr_;
319 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
320 assert(expr_);
322 expr_->type_ = IVL_EX_SELECT;
323 expr_->value_= IVL_VT_VECTOR;
324 expr_->width_= net->expr_width();
325 expr_->signed_ = net->has_sign()? 1 : 0;
327 expr_->u_.binary_.lef_ = left;
328 expr_->u_.binary_.rig_ = rght;
331 void dll_target::expr_sfunc(const NetESFunc*net)
333 assert(expr_ == 0);
335 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
336 assert(expr);
338 expr->type_ = IVL_EX_SFUNC;
339 FILE_NAME(expr, net);
340 expr->value_= net->expr_type();
341 expr->width_= net->expr_width();
342 expr->signed_ = net->has_sign()? 1 : 0;
343 /* system function names are lex_strings strings. */
344 expr->u_.sfunc_.name_ = net->name();
346 unsigned cnt = net->nparms();
347 expr->u_.sfunc_.parms = cnt;
348 expr->u_.sfunc_.parm = new ivl_expr_t[cnt];
350 /* make up the parameter expressions. */
351 for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
352 net->parm(idx)->expr_scan(this);
353 assert(expr_);
354 expr->u_.sfunc_.parm[idx] = expr_;
355 expr_ = 0;
358 expr_ = expr;
361 void dll_target::expr_ternary(const NetETernary*net)
363 assert(expr_ == 0);
365 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
366 assert(expr);
368 expr->type_ = IVL_EX_TERNARY;
369 FILE_NAME(expr, net);
370 expr->value_= net->expr_type();
371 expr->width_ = net->expr_width();
372 expr->signed_ = net->has_sign()? 1 : 0;
374 net->cond_expr()->expr_scan(this);
375 assert(expr_);
376 expr->u_.ternary_.cond = expr_;
377 expr_ = 0;
379 net->true_expr()->expr_scan(this);
380 assert(expr_);
381 expr->u_.ternary_.true_e = expr_;
382 expr_ = 0;
384 net->false_expr()->expr_scan(this);
385 assert(expr_);
386 expr->u_.ternary_.false_e = expr_;
388 expr_ = expr;
391 void dll_target::expr_signal(const NetESignal*net)
393 ivl_signal_t sig = find_signal(des_, net->sig());
395 assert(expr_ == 0);
397 /* If there is a word expression, generate it. */
398 ivl_expr_t word_expr = 0;
399 if (const NetExpr*word = net->word_index()) {
400 word->expr_scan(this);
401 assert(expr_);
402 word_expr = expr_;
403 expr_ = 0;
406 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
407 assert(expr_);
409 expr_->type_ = IVL_EX_SIGNAL;
410 expr_->value_= net->expr_type();
411 expr_->file = net->get_file();
412 expr_->lineno= net->get_lineno();
413 expr_->width_= net->expr_width();
414 expr_->signed_ = net->has_sign()? 1 : 0;
415 expr_->u_.signal_.word = word_expr;
416 expr_->u_.signal_.sig = sig;
418 /* Make account for the special case that this is a reference
419 to an array as a whole. We detect this case by noting that
420 this is an array (more than 1 word) and there is no word
421 select expression. In that case, this is an IVL_EX_ARRAY
422 expression instead of a SIGNAL expression. */
423 if (sig->array_words > 1 && word_expr == 0) {
424 expr_->type_ = IVL_EX_ARRAY;
425 expr_->width_ = 0; // Doesn't make much sense for arrays.
430 void dll_target::expr_ufunc(const NetEUFunc*net)
432 assert(expr_ == 0);
434 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
435 assert(expr);
437 expr->type_ = IVL_EX_UFUNC;
438 FILE_NAME(expr, net);
439 expr->value_= net->expr_type();
440 expr->width_= net->expr_width();
441 expr->signed_ = net->has_sign()? 1 : 0;
443 expr->u_.ufunc_.def = lookup_scope_(net->func());
444 assert(expr->u_.ufunc_.def->type_ == IVL_SCT_FUNCTION);
446 unsigned cnt = net->parm_count();
447 expr->u_.ufunc_.parms = cnt;
448 expr->u_.ufunc_.parm = new ivl_expr_t[cnt];
450 /* make up the parameter expressions. */
451 for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
452 net->parm(idx)->expr_scan(this);
453 assert(expr_);
454 expr->u_.ufunc_.parm[idx] = expr_;
455 expr_ = 0;
458 expr_ = expr;
461 void dll_target::expr_unary(const NetEUnary*net)
463 assert(expr_ == 0);
465 net->expr()->expr_scan(this);
466 assert(expr_);
468 ivl_expr_t sub = expr_;
470 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
471 expr_->type_ = IVL_EX_UNARY;
472 expr_->value_= net->expr_type();
473 expr_->width_ = net->expr_width();
474 expr_->signed_ = net->has_sign()? 1 : 0;
475 expr_->u_.unary_.op_ = net->op();
476 expr_->u_.unary_.sub_ = sub;