2 * Copyright (c) 2000 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
20 #ident "$Id: t-dll-expr.cc,v 1.47 2007/03/22 16:08:18 steve Exp $"
36 * This is a little convenience function for converting a NetExpr
37 * expression type to the expression type used by ivl_expr_t objects.
39 static ivl_variable_type_t
get_expr_type(const NetExpr
*net
)
41 return net
->expr_type();
45 * These methods implement the expression scan that generates the
46 * ivl_expr_t representing the expression. Each method leaves the
47 * expr_ member filled with the ivl_expr_t that represents it. Each
48 * method expects that the expr_ member empty (0) when it starts.
52 * This function takes an expression in the expr_ member that is
53 * already built up, and adds a subtraction of the given constant.
55 void dll_target::sub_off_from_expr_(long off
)
60 ivl_expr_t tmpc
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
61 tmpc
->type_
= IVL_EX_NUMBER
;
62 tmpc
->value_
= IVL_VT_VECTOR
;
63 tmpc
->width_
= expr_
->width_
;
64 tmpc
->signed_
= expr_
->signed_
;
65 tmpc
->u_
.number_
.bits_
= bits
= (char*)malloc(tmpc
->width_
);
66 for (unsigned idx
= 0 ; idx
< tmpc
->width_
; idx
+= 1) {
67 bits
[idx
] = (off
& 1)? '1' : '0';
71 /* Now make the subtractor (x-4 in the above example)
72 that has as input A the index expression and input B
73 the constant to subtract. */
74 ivl_expr_t tmps
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
75 tmps
->type_
= IVL_EX_BINARY
;
76 tmps
->value_
= IVL_VT_VECTOR
;
77 tmps
->width_
= tmpc
->width_
;
78 tmps
->signed_
= tmpc
->signed_
;
79 tmps
->u_
.binary_
.op_
= '-';
80 tmps
->u_
.binary_
.lef_
= expr_
;
81 tmps
->u_
.binary_
.rig_
= tmpc
;
83 /* Replace (x) with (x-off) */
87 void dll_target::mul_expr_by_const_(long val
)
92 ivl_expr_t tmpc
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
93 tmpc
->type_
= IVL_EX_NUMBER
;
94 tmpc
->value_
= IVL_VT_VECTOR
;
95 tmpc
->width_
= expr_
->width_
;
96 tmpc
->signed_
= expr_
->signed_
;
97 tmpc
->u_
.number_
.bits_
= bits
= (char*)malloc(tmpc
->width_
);
98 for (unsigned idx
= 0 ; idx
< tmpc
->width_
; idx
+= 1) {
99 bits
[idx
] = (val
& 1)? '1' : '0';
103 /* Now make the subtractor (x-4 in the above example)
104 that has as input A the index expression and input B
105 the constant to subtract. */
106 ivl_expr_t tmps
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
107 tmps
->type_
= IVL_EX_BINARY
;
108 tmps
->value_
= IVL_VT_VECTOR
;
109 tmps
->width_
= tmpc
->width_
;
110 tmps
->signed_
= tmpc
->signed_
;
111 tmps
->u_
.binary_
.op_
= '*';
112 tmps
->u_
.binary_
.lef_
= expr_
;
113 tmps
->u_
.binary_
.rig_
= tmpc
;
115 /* Replace (x) with (x*valf) */
119 ivl_expr_t
dll_target::expr_from_value_(const verinum
&val
)
121 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
126 expr
->type_
= IVL_EX_NUMBER
;
127 expr
->value_
= IVL_VT_VECTOR
;
128 expr
->width_
= val
.len();
129 expr
->signed_
= val
.has_sign()? 1 : 0;
130 expr
->u_
.number_
.bits_
= bits
= (char*)malloc(expr
->width_
+ 1);
131 for (idx
= 0 ; idx
< expr
->width_
; idx
+= 1)
132 switch (val
.get(idx
)) {
149 bits
[expr
->width_
] = 0;
154 void dll_target::expr_binary(const NetEBinary
*net
)
158 net
->left()->expr_scan(this);
159 ivl_expr_t left
= expr_
;
162 net
->right()->expr_scan(this);
163 ivl_expr_t rght
= expr_
;
165 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
168 expr_
->type_
= IVL_EX_BINARY
;
169 expr_
->value_
= get_expr_type(net
);
170 expr_
->width_
= net
->expr_width();
171 expr_
->signed_
= net
->has_sign()? 1 : 0;
173 expr_
->u_
.binary_
.op_
= net
->op();
174 expr_
->u_
.binary_
.lef_
= left
;
175 expr_
->u_
.binary_
.rig_
= rght
;
178 void dll_target::expr_concat(const NetEConcat
*net
)
182 ivl_expr_t cur
= new struct ivl_expr_s
;
185 cur
->type_
= IVL_EX_CONCAT
;
186 cur
->value_
= IVL_VT_VECTOR
;
187 cur
->width_
= net
->expr_width();
189 cur
->u_
.concat_
.rept
= net
->repeat();
190 cur
->u_
.concat_
.parms
= net
->nparms();
191 cur
->u_
.concat_
.parm
= new ivl_expr_t
[net
->nparms()];
193 for (unsigned idx
= 0 ; idx
< net
->nparms() ; idx
+= 1) {
195 net
->parm(idx
)->expr_scan(this);
197 cur
->u_
.concat_
.parm
[idx
] = expr_
;
203 void dll_target::expr_const(const NetEConst
*net
)
207 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
209 expr_
->value_
= net
->expr_type();
211 if (net
->value().is_string()) {
212 expr_
->type_
= IVL_EX_STRING
;
213 expr_
->width_
= net
->expr_width();
214 expr_
->u_
.string_
.value_
=strdup(net
->value().as_string().c_str());
217 verinum val
= net
->value();
220 expr_
->type_
= IVL_EX_NUMBER
;
221 expr_
->width_
= net
->expr_width();
222 expr_
->signed_
= net
->has_sign()? 1 : 0;
223 expr_
->u_
.number_
.bits_
= bits
= (char*)malloc(expr_
->width_
);
224 for (idx
= 0 ; idx
< expr_
->width_
; idx
+= 1)
225 switch (val
.get(idx
)) {
245 void dll_target::expr_param(const NetEConstParam
*net
)
247 ivl_scope_t scope
= find_scope(des_
, net
->scope());
248 ivl_parameter_t par
= scope_find_param(scope
, net
->name());
251 cerr
<< net
->get_line() << ": internal error: "
252 << "Parameter " << net
->name() << " missing from "
253 << ivl_scope_name(scope
) << endl
;
260 void dll_target::expr_creal(const NetECReal
*net
)
263 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
264 expr_
->width_
= net
->expr_width();
266 expr_
->type_
= IVL_EX_REALNUM
;
267 expr_
->value_
= IVL_VT_REAL
;
268 expr_
->u_
.real_
.value
= net
->value().as_double();
271 void dll_target::expr_event(const NetEEvent
*net
)
275 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
278 expr_
->type_
= IVL_EX_EVENT
;
279 expr_
->value_
= IVL_VT_VOID
;
281 /* Locate the event by name. Save the ivl_event_t in the
282 expression so that the generator can find it easily. */
283 const NetEvent
*ev
= net
->event();
284 ivl_scope_t ev_scope
= lookup_scope_(ev
->scope());
286 for (unsigned idx
= 0 ; idx
< ev_scope
->nevent_
; idx
+= 1) {
287 const char*ename
= ivl_event_basename(ev_scope
->event_
[idx
]);
288 if (strcmp(ev
->name(), ename
) == 0) {
289 expr_
->u_
.event_
.event
= ev_scope
->event_
[idx
];
295 void dll_target::expr_scope(const NetEScope
*net
)
299 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
302 expr_
->type_
= IVL_EX_SCOPE
;
303 expr_
->value_
= IVL_VT_VOID
;
304 expr_
->u_
.scope_
.scope
= lookup_scope_(net
->scope());
307 void dll_target::expr_select(const NetESelect
*net
)
311 net
->sub_expr()->expr_scan(this);
312 ivl_expr_t left
= expr_
;
316 net
->select()->expr_scan(this);
318 ivl_expr_t rght
= expr_
;
320 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
323 expr_
->type_
= IVL_EX_SELECT
;
324 expr_
->value_
= IVL_VT_VECTOR
;
325 expr_
->width_
= net
->expr_width();
326 expr_
->signed_
= net
->has_sign()? 1 : 0;
328 expr_
->u_
.binary_
.lef_
= left
;
329 expr_
->u_
.binary_
.rig_
= rght
;
332 void dll_target::expr_sfunc(const NetESFunc
*net
)
336 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
339 expr
->type_
= IVL_EX_SFUNC
;
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 expr
->value_
= net
->expr_type();
370 expr
->width_
= net
->expr_width();
371 expr
->signed_
= net
->has_sign()? 1 : 0;
373 net
->cond_expr()->expr_scan(this);
375 expr
->u_
.ternary_
.cond
= expr_
;
378 net
->true_expr()->expr_scan(this);
380 expr
->u_
.ternary_
.true_e
= expr_
;
383 net
->false_expr()->expr_scan(this);
385 expr
->u_
.ternary_
.false_e
= expr_
;
390 void dll_target::expr_signal(const NetESignal
*net
)
392 ivl_signal_t sig
= find_signal(des_
, net
->sig());
396 /* If there is a word expression, generate it. */
397 ivl_expr_t word_expr
= 0;
398 if (const NetExpr
*word
= net
->word_index()) {
399 word
->expr_scan(this);
405 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
408 expr_
->type_
= IVL_EX_SIGNAL
;
409 expr_
->value_
= net
->expr_type();
410 expr_
->width_
= net
->expr_width();
411 expr_
->signed_
= net
->has_sign()? 1 : 0;
412 expr_
->u_
.signal_
.word
= word_expr
;
413 expr_
->u_
.signal_
.sig
= sig
;
415 /* Make account for the special case that this is a reference
416 to an array as a whole. We detect this case by noting that
417 this is an array (more than 1 word) and there is no word
418 select expression. In that case, this is an IVL_EX_ARRAY
419 expression instead of a SIGNAL expression. */
420 if (sig
->array_words
> 1 && word_expr
== 0) {
421 expr_
->type_
= IVL_EX_ARRAY
;
422 expr_
->width_
= 0; // Doesn't make much sense for arrays.
427 void dll_target::expr_ufunc(const NetEUFunc
*net
)
431 ivl_expr_t expr
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
434 expr
->type_
= IVL_EX_UFUNC
;
435 expr
->value_
= net
->expr_type();
436 expr
->width_
= net
->expr_width();
437 expr
->signed_
= net
->has_sign()? 1 : 0;
439 expr
->u_
.ufunc_
.def
= lookup_scope_(net
->func());
440 assert(expr
->u_
.ufunc_
.def
->type_
== IVL_SCT_FUNCTION
);
442 unsigned cnt
= net
->parm_count();
443 expr
->u_
.ufunc_
.parms
= cnt
;
444 expr
->u_
.ufunc_
.parm
= new ivl_expr_t
[cnt
];
446 /* make up the parameter expressions. */
447 for (unsigned idx
= 0 ; idx
< cnt
; idx
+= 1) {
448 net
->parm(idx
)->expr_scan(this);
450 expr
->u_
.ufunc_
.parm
[idx
] = expr_
;
457 void dll_target::expr_unary(const NetEUnary
*net
)
461 net
->expr()->expr_scan(this);
464 ivl_expr_t sub
= expr_
;
466 expr_
= (ivl_expr_t
)calloc(1, sizeof(struct ivl_expr_s
));
467 expr_
->type_
= IVL_EX_UNARY
;
468 expr_
->value_
= net
->expr_type();
469 expr_
->width_
= net
->expr_width();
470 expr_
->signed_
= net
->has_sign()? 1 : 0;
471 expr_
->u_
.unary_
.op_
= net
->op();
472 expr_
->u_
.unary_
.sub_
= sub
;
476 * $Log: t-dll-expr.cc,v $
477 * Revision 1.47 2007/03/22 16:08:18 steve
478 * Spelling fixes from Larry
480 * Revision 1.46 2007/02/20 05:58:36 steve
481 * Handle unary minus of real valued expressions.
483 * Revision 1.45 2007/02/14 05:59:46 steve
484 * Handle type of ternary expressions properly.
486 * Revision 1.44 2007/01/16 05:44:15 steve
487 * Major rework of array handling. Memories are replaced with the
488 * more general concept of arrays. The NetMemory and NetEMemory
489 * classes are removed from the ivl core program, and the IVL_LPM_RAM
490 * lpm type is removed from the ivl_target API.
492 * Revision 1.43 2005/09/14 02:53:15 steve
493 * Support bool expressions and compares handle them optimally.
495 * Revision 1.42 2005/07/13 04:51:36 steve
496 * Functions get type from their output signal.
498 * Revision 1.41 2005/07/11 16:56:51 steve
499 * Remove NetVariable and ivl_variable_t structures.
501 * Revision 1.40 2005/01/24 05:28:31 steve
502 * Remove the NetEBitSel and combine all bit/part select
503 * behavior into the NetESelect node and IVL_EX_SELECT
504 * ivl_target expression type.
506 * Revision 1.39 2004/06/17 16:06:19 steve
507 * Help system function signedness survive elaboration.
509 * Revision 1.38 2003/07/26 03:34:43 steve
510 * Start handling pad of expressions in code generators.
512 * Revision 1.37 2003/06/24 01:38:03 steve
513 * Various warnings fixed.
515 * Revision 1.36 2003/04/22 04:48:30 steve
516 * Support event names as expressions elements.
518 * Revision 1.35 2003/03/10 23:40:53 steve
519 * Keep parameter constants for the ivl_target API.
521 * Revision 1.34 2003/03/01 06:25:30 steve
522 * Add the lex_strings string handler, and put
523 * scope names and system task/function names
524 * into this table. Also, permallocate event
525 * names from the beginning.
527 * Revision 1.33 2003/02/02 00:19:27 steve
528 * Terminate bits string from ivl_expr_bits.
530 * Revision 1.32 2003/01/30 16:23:08 steve
533 * Revision 1.31 2003/01/27 00:14:37 steve
534 * Support in various contexts the $realtime
537 * Revision 1.30 2003/01/26 21:15:59 steve
538 * Rework expression parsing and elaboration to
539 * accommodate real/realtime values and expressions.
541 * Revision 1.29 2002/10/23 01:47:17 steve
542 * Fix synth2 handling of aset/aclr signals where
543 * flip-flops are split by begin-end blocks.
545 * Revision 1.28 2002/08/12 01:35:00 steve
546 * conditional ident string using autoconfig.
548 * Revision 1.27 2002/08/04 18:28:15 steve
549 * Do not use hierarchical names of memories to
550 * generate vvp labels. -tdll target does not
551 * used hierarchical name string to look up the
552 * memory objects in the design.
554 * Revision 1.26 2002/06/16 20:39:12 steve
555 * Normalize run-time index expressions for bit selects
557 * Revision 1.25 2002/06/16 19:19:16 steve
558 * Generate runtime code to normalize indices.
560 * Revision 1.24 2002/05/29 22:05:54 steve
561 * Offset lvalue index expressions.
563 * Revision 1.23 2002/04/14 02:56:19 steve
564 * Support signed expressions through to VPI.
566 * Revision 1.22 2002/01/28 00:52:41 steve
567 * Add support for bit select of parameters.
568 * This leads to a NetESelect node and the
569 * vvp code generator to support that.
571 * Revision 1.21 2001/12/31 00:08:14 steve
572 * Support $signed cast of expressions.
574 * Revision 1.20 2001/10/23 04:22:41 steve
575 * Support bit selects of non-0 lsb for vectors.
577 * Revision 1.19 2001/10/19 21:53:24 steve
578 * Support multiple root modules (Philip Blundell)
580 * Revision 1.18 2001/09/15 18:27:04 steve
581 * Make configure detect malloc.h
583 * Revision 1.17 2001/07/27 04:51:44 steve
584 * Handle part select expressions as variants of
585 * NetESignal/IVL_EX_SIGNAL objects, instead of
586 * creating new and useless temporary signals.
588 * Revision 1.16 2001/07/25 03:10:49 steve
589 * Create a config.h.in file to hold all the config
590 * junk, and support gcc 3.0. (Stephan Boettcher)
592 * Revision 1.15 2001/07/22 00:17:49 steve
593 * Support the NetESubSignal expressions in vvp.tgt.
595 * Revision 1.14 2001/07/07 20:20:10 steve
596 * Pass parameters to system functions.
598 * Revision 1.13 2001/05/17 04:37:02 steve
599 * Behavioral ternary operators for vvp.
601 * Revision 1.12 2001/05/08 23:59:33 steve
602 * Add ivl and vvp.tgt support for memories in
603 * expressions and l-values. (Stephan Boettcher)