Handle nil parameter overrides
[iverilog.git] / net_expr.cc
blob780928cef74098b9fce3f5e72ce74df9cfa894c4
1 /*
2 * Copyright (c) 2002 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: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
21 #endif
23 # include "config.h"
24 # include "netlist.h"
25 # include "compiler.h"
26 # include <iostream>
29 * the grand default data type is a logic vector.
31 ivl_variable_type_t NetExpr::expr_type() const
33 return IVL_VT_LOGIC;
37 * Create an add/sub node from the two operands. Make a best guess of
38 * the
40 NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
41 : NetEBinary(op, l, r)
43 NetEConst* tmp;
45 /* Catch the special case that one of the operands is an
46 unsized constant number. If so, then we should set the
47 width of that number to the size of the other operand, plus
48 one. This expands the expression to account for the largest
49 possible result.
51 The set_width applied to a constant value will only
52 truncate the constant so far as it can still hold its
53 logical value, so this is safe to do. */
54 if ( (tmp = dynamic_cast<NetEConst*>(r))
55 && (! tmp->has_width())
56 && (tmp->expr_width() > l->expr_width()) ) {
58 unsigned target_width = l->expr_width() + 1;
59 r->set_width(target_width);
61 /* Note: This constant value will not gain a defined
62 width from this. Make sure. */
63 assert(! r->has_width() );
65 } else if ( (tmp = dynamic_cast<NetEConst*>(l))
66 && (! tmp->has_width())
67 && (tmp->expr_width() > r->expr_width()) ) {
69 unsigned target_width = r->expr_width() + 1;
70 l->set_width(target_width);
72 /* Note: This constant value will not gain a defined
73 width from this. Make sure. */
74 assert(! l->has_width() );
78 unsigned pad_width = lossless_flag? 1 : 0;
80 /* Now that we have the operand sizes the way we like, or as
81 good as we are going to get them, set the size of myself. */
82 if (r->expr_width() > l->expr_width()) {
84 expr_width(r->expr_width() + pad_width);
86 } else {
87 expr_width(l->expr_width() + pad_width);
90 cast_signed(l->has_sign() && r->has_sign());
93 NetEBAdd::~NetEBAdd()
97 NetEBAdd* NetEBAdd::dup_expr() const
99 NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
100 right_->dup_expr());
101 return result;
104 ivl_variable_type_t NetEBAdd::expr_type() const
106 if (left_->expr_type() == IVL_VT_REAL)
107 return IVL_VT_REAL;
109 if (right_->expr_type() == IVL_VT_REAL)
110 return IVL_VT_REAL;
112 return IVL_VT_LOGIC;
116 * Create a comparison operator with two sub-expressions.
118 * Handle the special case of an unsized constant on the left or right
119 * side by resizing the number to match the other
120 * expression. Otherwise, the netlist will have to allow the
121 * expressions to have different widths.
123 NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
124 : NetEBinary(op, l, r)
126 if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
128 if (tmp->has_width())
129 break;
131 if (l->expr_width() == 0)
132 break;
134 if (tmp->expr_width() == l->expr_width())
135 break;
137 tmp->set_width(l->expr_width());
139 } while (0);
141 if (NetEConst*tmp = dynamic_cast<NetEConst*>(l)) do {
143 if (tmp->has_width())
144 break;
146 if (r->expr_width() == 0)
147 break;
149 if (tmp->expr_width() == r->expr_width())
150 break;
152 tmp->set_width(r->expr_width());
154 } while (0);
157 expr_width(1);
160 NetEBComp::~NetEBComp()
164 bool NetEBComp::has_width() const
166 return true;
169 ivl_variable_type_t NetEBComp::expr_type() const
171 // Case compare always returns BOOL
172 if (op() == 'E' || op() == 'N')
173 return IVL_VT_BOOL;
175 if (left()->expr_type() == IVL_VT_LOGIC)
176 return IVL_VT_LOGIC;
178 if (right()->expr_type() == IVL_VT_LOGIC)
179 return IVL_VT_LOGIC;
181 return IVL_VT_BOOL;
184 NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
185 : NetEBinary(op, l, r)
187 unsigned w = l->expr_width();
188 if (r->expr_width() > w)
189 w = r->expr_width();
191 expr_width(w);
192 cast_signed(l->has_sign() && r->has_sign());
195 NetEBDiv::~NetEBDiv()
199 NetEBDiv* NetEBDiv::dup_expr() const
201 NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
202 right_->dup_expr());
203 return result;
206 ivl_variable_type_t NetEBDiv::expr_type() const
208 if (left_->expr_type() == IVL_VT_REAL)
209 return IVL_VT_REAL;
211 if (right_->expr_type() == IVL_VT_REAL)
212 return IVL_VT_REAL;
214 return IVL_VT_LOGIC;
217 NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
218 : NetEBinary(op, l, r)
220 expr_width(l->expr_width() + r->expr_width());
221 cast_signed(l->has_sign() && r->has_sign());
223 /* If it turns out that this is not a signed expression, then
224 cast the signedness out of the operands as well. */
225 if (! has_sign()) {
226 l->cast_signed(false);
227 r->cast_signed(false);
231 NetEBMult::~NetEBMult()
235 NetEBMult* NetEBMult::dup_expr() const
237 NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
238 right_->dup_expr());
239 return result;
242 ivl_variable_type_t NetEBMult::expr_type() const
244 if (left_->expr_type() == IVL_VT_REAL)
245 return IVL_VT_REAL;
247 if (right_->expr_type() == IVL_VT_REAL)
248 return IVL_VT_REAL;
250 return IVL_VT_LOGIC;
253 NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
254 : NetEBinary(op, l, r)
256 assert(op == 'p');
257 expr_width(l->expr_width());
258 cast_signed(l->has_sign() || r->has_sign());
261 NetEBPow::~NetEBPow()
265 NetEBPow* NetEBPow::dup_expr() const
267 NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
268 right_->dup_expr());
269 result->set_line(*this);
270 return result;
273 ivl_variable_type_t NetEBPow::expr_type() const
275 if (right_->expr_type() == IVL_VT_REAL)
276 return IVL_VT_REAL;
277 if (left_->expr_type() == IVL_VT_REAL)
278 return IVL_VT_REAL;
279 if (left_->has_sign())
280 return IVL_VT_REAL;
281 if (right_->has_sign())
282 return IVL_VT_REAL;
284 return IVL_VT_LOGIC;
287 NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
288 : NetEBinary(op, l, r)
290 expr_width(l->expr_width());
292 // The >>> is signed if the left operand is signed.
293 if (op == 'R') cast_signed(l->has_sign());
296 NetEBShift::~NetEBShift()
300 bool NetEBShift::has_width() const
302 return left_->has_width();
305 NetEBShift* NetEBShift::dup_expr() const
307 NetEBShift*result = new NetEBShift(op_, left_->dup_expr(),
308 right_->dup_expr());
309 return result;
312 NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
313 : parms_(cnt), repeat_(r)
315 if (repeat_ == 0) {
316 repeat_calculated_ = true;
317 repeat_value_ = 1;
318 } else {
319 repeat_calculated_ = false;
322 expr_width(0);
325 NetEConcat::~NetEConcat()
327 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
328 delete parms_[idx];
331 bool NetEConcat::has_width() const
333 return true;
336 void NetEConcat::set(unsigned idx, NetExpr*e)
338 assert(idx < parms_.count());
339 assert(parms_[idx] == 0);
340 parms_[idx] = e;
341 expr_width( expr_width() + e->expr_width() );
344 NetEConcat* NetEConcat::dup_expr() const
346 NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
347 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
348 if (parms_[idx]) {
349 NetExpr*tmp = parms_[idx]->dup_expr();
350 assert(tmp);
351 dup->parms_[idx] = tmp;
355 dup->expr_width(expr_width());
356 return dup;
359 unsigned NetEConcat::repeat()
361 if (repeat_calculated_)
362 return repeat_value_;
364 assert(repeat_);
366 if (! dynamic_cast<NetEConst*>(repeat_)) {
367 NetExpr*tmp = repeat_->eval_tree();
368 if (tmp != 0) {
369 delete repeat_;
370 repeat_ = tmp;
374 NetEConst*repeat_const = dynamic_cast<NetEConst*>(repeat_);
376 /* This should not be possible, as it was checked earlier to
377 assure that this is a constant expression. */
378 if (repeat_const == 0) {
379 cerr << get_line() << ": internal error: repeat expression "
380 << "is not a compile time constant." << endl;
381 cerr << get_line() << ": : Expression is: "
382 << *repeat_ << endl;
383 repeat_calculated_ = true;
384 repeat_value_ = 1;
385 return 1;
388 repeat_calculated_ = true;
389 repeat_value_ = repeat_const->value().as_ulong();
391 delete repeat_;
392 repeat_ = 0;
394 return repeat_value_;
397 unsigned NetEConcat::repeat() const
399 assert(repeat_calculated_);
400 return repeat_value_;
403 NetECReal::NetECReal(const verireal&val)
404 : value_(val)
408 NetECReal::~NetECReal()
412 const verireal& NetECReal::value() const
414 return value_;
417 bool NetECReal::has_width() const
419 return false;
422 NetECReal* NetECReal::dup_expr() const
424 NetECReal*tmp = new NetECReal(value_);
425 tmp->set_line(*this);
426 return tmp;
429 ivl_variable_type_t NetECReal::expr_type() const
431 return IVL_VT_REAL;
434 NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
435 : NetECReal(v), scope_(s), name_(n)
439 NetECRealParam::~NetECRealParam()
443 perm_string NetECRealParam::name() const
445 return name_;
448 const NetScope* NetECRealParam::scope() const
450 return scope_;
454 NetEParam::NetEParam()
455 : des_(0), scope_(0)
459 NetEParam::NetEParam(Design*d, NetScope*s, perm_string n)
460 : des_(d), scope_(s), name_(n)
464 NetEParam::~NetEParam()
468 bool NetEParam::has_width() const
470 return false;
473 NetEParam* NetEParam::dup_expr() const
475 NetEParam*tmp = new NetEParam(des_, scope_, name_);
476 tmp->set_line(*this);
477 return tmp;
480 NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid)
481 : expr_(exp), base_(base)
483 expr_width(wid);
486 NetESelect::~NetESelect()
488 delete expr_;
489 delete base_;
492 const NetExpr*NetESelect::sub_expr() const
494 return expr_;
497 const NetExpr*NetESelect::select() const
499 return base_;
502 bool NetESelect::has_width() const
504 return true;
507 NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
508 unsigned width, unsigned np)
509 : name_(0), type_(t)
511 name_ = lex_strings.add(n);
512 expr_width(width);
513 nparms_ = np;
514 parms_ = new NetExpr*[np];
515 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
516 parms_[idx] = 0;
519 NetESFunc::~NetESFunc()
521 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
522 if (parms_[idx]) delete parms_[idx];
524 delete[]parms_;
525 /* name_ string ls lex_strings allocated. */
528 const char* NetESFunc::name() const
530 return name_;
533 unsigned NetESFunc::nparms() const
535 return nparms_;
538 void NetESFunc::parm(unsigned idx, NetExpr*v)
540 assert(idx < nparms_);
541 if (parms_[idx])
542 delete parms_[idx];
543 parms_[idx] = v;
546 const NetExpr* NetESFunc::parm(unsigned idx) const
548 assert(idx < nparms_);
549 return parms_[idx];
552 NetExpr* NetESFunc::parm(unsigned idx)
554 assert(idx < nparms_);
555 return parms_[idx];
558 ivl_variable_type_t NetESFunc::expr_type() const
560 return type_;
564 * $Log: net_expr.cc,v $
565 * Revision 1.27 2006/07/31 03:50:17 steve
566 * Add support for power in constant expressions.
568 * Revision 1.26 2005/11/26 00:35:43 steve
569 * More precise about r-value width of constants.
571 * Revision 1.25 2005/09/14 02:53:14 steve
572 * Support bool expressions and compares handle them optimally.
574 * Revision 1.24 2005/07/11 16:56:50 steve
575 * Remove NetVariable and ivl_variable_t structures.
577 * Revision 1.23 2004/10/04 01:10:54 steve
578 * Clean up spurious trailing white space.
580 * Revision 1.22 2004/02/20 06:22:56 steve
581 * parameter keys are per_strings.
583 * Revision 1.21 2003/08/28 04:11:19 steve
584 * Spelling patch.
586 * Revision 1.20 2003/06/18 03:55:18 steve
587 * Add arithmetic shift operators.
589 * Revision 1.19 2003/06/15 18:53:20 steve
590 * Operands of unsigned multiply are unsigned.
592 * Revision 1.18 2003/05/30 02:55:32 steve
593 * Support parameters in real expressions and
594 * as real expressions, and fix multiply and
595 * divide with real results.
597 * Revision 1.17 2003/05/20 15:05:33 steve
598 * Do not try to set constants to width 0.
600 * Revision 1.16 2003/03/15 18:08:43 steve
601 * Comparison operators do have defined width.
603 * Revision 1.15 2003/03/15 04:46:29 steve
604 * Better organize the NetESFunc return type guesses.
606 * Revision 1.14 2003/03/01 06:25:30 steve
607 * Add the lex_strings string handler, and put
608 * scope names and system task/function names
609 * into this table. Also, permallocate event
610 * names from the beginning.
612 * Revision 1.13 2003/02/06 17:50:23 steve
613 * Real constants have no defined vector width
615 * Revision 1.12 2003/01/27 00:14:37 steve
616 * Support in various contexts the $realtime
617 * system task.
619 * Revision 1.11 2003/01/26 21:15:58 steve
620 * Rework expression parsing and elaboration to
621 * accommodate real/realtime values and expressions.
623 * Revision 1.10 2002/11/09 01:40:19 steve
624 * Postpone parameter width check to evaluation.
626 * Revision 1.9 2002/11/06 02:25:13 steve
627 * No need to keep excess width from an
628 * unsigned constant value, if it can
629 * be trimmed safely.
631 * Revision 1.8 2002/10/19 22:59:49 steve
632 * Redo the parameter vector support to allow
633 * parameter names in range expressions.
635 * Revision 1.7 2002/09/01 03:01:48 steve
636 * Properly cast signedness of parameters with ranges.
638 * Revision 1.6 2002/08/12 01:34:59 steve
639 * conditional ident string using autoconfig.
641 * Revision 1.5 2002/06/06 18:57:18 steve
642 * Use standard name for iostream.
644 * Revision 1.4 2002/05/25 16:51:37 steve
645 * include iostream for gcc 3.1
647 * Revision 1.3 2002/05/05 21:11:50 steve
648 * Put off evaluation of concatenation repeat expresions
649 * until after parameters are defined. This allows parms
650 * to be used in repeat expresions.
652 * Add the builtin $signed system function.
654 * Revision 1.2 2002/01/29 22:36:31 steve
655 * include config.h to eliminate warnings.
657 * Revision 1.1 2002/01/28 01:39:45 steve
658 * Add ne_expr.cc