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)
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
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
)
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';
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) */
85 void dll_target::mul_expr_by_const_(long val
)
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';
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) */
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
));
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
)) {
147 bits
[expr
->width_
] = 0;
152 void dll_target::expr_binary(const NetEBinary
*net
)
156 net
->left()->expr_scan(this);
157 ivl_expr_t left
= expr_
;
160 net
->right()->expr_scan(this);
161 ivl_expr_t rght
= expr_
;
163 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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
)
180 ivl_expr_t cur
= new struct ivl_expr_s
;
183 cur
->type_
= IVL_EX_CONCAT
;
184 cur
->value_
= IVL_VT_VECTOR
;
185 cur
->width_
= net
->expr_width();
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) {
194 net
->parm(idx
)->expr_scan(this);
196 cur
->u_
.concat_
.parm
[idx
] = expr_
;
202 void dll_target::expr_const(const NetEConst
*net
)
206 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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());
216 verinum val
= net
->value();
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
)) {
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());
250 cerr
<< net
->get_fileline() << ": internal error: "
251 << "Parameter " << net
->name() << " missing from "
252 << ivl_scope_name(scope
) << endl
;
259 void dll_target::expr_creal(const NetECReal
*net
)
262 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
263 expr_
->width_
= net
->expr_width();
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
)
274 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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
];
294 void dll_target::expr_scope(const NetEScope
*net
)
298 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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
)
310 net
->sub_expr()->expr_scan(this);
311 ivl_expr_t left
= expr_
;
315 net
->select()->expr_scan(this);
317 ivl_expr_t rght
= expr_
;
319 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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
)
335 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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);
354 expr
->u_
.sfunc_
.parm
[idx
] = expr_
;
361 void dll_target::expr_ternary(const NetETernary
*net
)
365 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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);
376 expr
->u_
.ternary_
.cond
= expr_
;
379 net
->true_expr()->expr_scan(this);
381 expr
->u_
.ternary_
.true_e
= expr_
;
384 net
->false_expr()->expr_scan(this);
386 expr
->u_
.ternary_
.false_e
= expr_
;
391 void dll_target::expr_signal(const NetESignal
*net
)
393 ivl_signal_t sig
= find_signal(des_
, net
->sig());
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);
406 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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
)
434 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
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);
454 expr
->u_
.ufunc_
.parm
[idx
] = expr_
;
461 void dll_target::expr_unary(const NetEUnary
*net
)
465 net
->expr()->expr_scan(this);
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
;