$finish() now stops at the end of the time step not immediately.
[iverilog.git] / t-dll-expr.cc
blob8b4990494f88a17d412eb1ccd2904b9d99a2bf01
1 /*
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)
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: t-dll-expr.cc,v 1.47 2007/03/22 16:08:18 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
27 # include "t-dll.h"
28 # include "netlist.h"
29 # include <assert.h>
30 #ifdef HAVE_MALLOC_H
31 # include <malloc.h>
32 #endif
33 # include <stdlib.h>
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)
57 assert(expr_ != 0);
59 char*bits;
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';
68 off >>= 1;
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) */
84 expr_ = tmps;
87 void dll_target::mul_expr_by_const_(long val)
89 assert(expr_ != 0);
91 char*bits;
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';
100 val >>= 1;
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) */
116 expr_ = tmps;
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));
122 assert(expr);
124 unsigned idx;
125 char*bits;
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)) {
133 case verinum::V0:
134 bits[idx] = '0';
135 break;
136 case verinum::V1:
137 bits[idx] = '1';
138 break;
139 case verinum::Vx:
140 bits[idx] = 'x';
141 break;
142 case verinum::Vz:
143 bits[idx] = 'z';
144 break;
145 default:
146 assert(0);
149 bits[expr->width_] = 0;
151 return expr;
154 void dll_target::expr_binary(const NetEBinary*net)
156 assert(expr_ == 0);
158 net->left()->expr_scan(this);
159 ivl_expr_t left = expr_;
161 expr_ = 0;
162 net->right()->expr_scan(this);
163 ivl_expr_t rght = expr_;
165 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
166 assert(expr_);
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)
180 assert(expr_ == 0);
182 ivl_expr_t cur = new struct ivl_expr_s;
183 assert(cur);
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) {
194 expr_ = 0;
195 net->parm(idx)->expr_scan(this);
196 assert(expr_);
197 cur->u_.concat_.parm[idx] = expr_;
200 expr_ = cur;
203 void dll_target::expr_const(const NetEConst*net)
205 assert(expr_ == 0);
207 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
208 assert(expr_);
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());
216 } else {
217 verinum val = net->value();
218 unsigned idx;
219 char*bits;
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)) {
226 case verinum::V0:
227 bits[idx] = '0';
228 break;
229 case verinum::V1:
230 bits[idx] = '1';
231 break;
232 case verinum::Vx:
233 bits[idx] = 'x';
234 break;
235 case verinum::Vz:
236 bits[idx] = 'z';
237 break;
238 default:
239 assert(0);
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());
250 if (par == 0) {
251 cerr << net->get_line() << ": internal error: "
252 << "Parameter " << net->name() << " missing from "
253 << ivl_scope_name(scope) << endl;
255 assert(par);
256 assert(par->value);
257 expr_ = par->value;
260 void dll_target::expr_creal(const NetECReal*net)
262 assert(expr_ == 0);
263 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
264 expr_->width_ = net->expr_width();
265 expr_->signed_ = 1;
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)
273 assert(expr_ == 0);
275 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
276 assert(expr_);
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];
290 break;
295 void dll_target::expr_scope(const NetEScope*net)
297 assert(expr_ == 0);
299 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
300 assert(expr_);
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)
309 assert(expr_ == 0);
311 net->sub_expr()->expr_scan(this);
312 ivl_expr_t left = expr_;
314 expr_ = 0;
315 if (net->select())
316 net->select()->expr_scan(this);
318 ivl_expr_t rght = expr_;
320 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
321 assert(expr_);
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)
334 assert(expr_ == 0);
336 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
337 assert(expr);
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);
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 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);
374 assert(expr_);
375 expr->u_.ternary_.cond = expr_;
376 expr_ = 0;
378 net->true_expr()->expr_scan(this);
379 assert(expr_);
380 expr->u_.ternary_.true_e = expr_;
381 expr_ = 0;
383 net->false_expr()->expr_scan(this);
384 assert(expr_);
385 expr->u_.ternary_.false_e = expr_;
387 expr_ = expr;
390 void dll_target::expr_signal(const NetESignal*net)
392 ivl_signal_t sig = find_signal(des_, net->sig());
394 assert(expr_ == 0);
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);
400 assert(expr_);
401 word_expr = expr_;
402 expr_ = 0;
405 expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
406 assert(expr_);
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)
429 assert(expr_ == 0);
431 ivl_expr_t expr = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
432 assert(expr);
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);
449 assert(expr_);
450 expr->u_.ufunc_.parm[idx] = expr_;
451 expr_ = 0;
454 expr_ = expr;
457 void dll_target::expr_unary(const NetEUnary*net)
459 assert(expr_ == 0);
461 net->expr()->expr_scan(this);
462 assert(expr_);
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
531 * Spelling fixes.
533 * Revision 1.31 2003/01/27 00:14:37 steve
534 * Support in various contexts the $realtime
535 * system task.
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)