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)
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: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
25 # include "compiler.h"
29 * the grand default data type is a logic vector.
31 ivl_variable_type_t
NetExpr::expr_type() const
37 * Create an add/sub node from the two operands. Make a best guess of
40 NetEBAdd::NetEBAdd(char op
, NetExpr
*l
, NetExpr
*r
, bool lossless_flag
)
41 : NetEBinary(op
, l
, r
)
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
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
);
87 expr_width(l
->expr_width() + pad_width
);
90 cast_signed(l
->has_sign() && r
->has_sign());
97 NetEBAdd
* NetEBAdd::dup_expr() const
99 NetEBAdd
*result
= new NetEBAdd(op_
, left_
->dup_expr(),
104 ivl_variable_type_t
NetEBAdd::expr_type() const
106 if (left_
->expr_type() == IVL_VT_REAL
)
109 if (right_
->expr_type() == IVL_VT_REAL
)
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())
131 if (l
->expr_width() == 0)
134 if (tmp
->expr_width() == l
->expr_width())
137 tmp
->set_width(l
->expr_width());
141 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(l
)) do {
143 if (tmp
->has_width())
146 if (r
->expr_width() == 0)
149 if (tmp
->expr_width() == r
->expr_width())
152 tmp
->set_width(r
->expr_width());
160 NetEBComp::~NetEBComp()
164 bool NetEBComp::has_width() const
169 ivl_variable_type_t
NetEBComp::expr_type() const
171 // Case compare always returns BOOL
172 if (op() == 'E' || op() == 'N')
175 if (left()->expr_type() == IVL_VT_LOGIC
)
178 if (right()->expr_type() == IVL_VT_LOGIC
)
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
)
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(),
206 ivl_variable_type_t
NetEBDiv::expr_type() const
208 if (left_
->expr_type() == IVL_VT_REAL
)
211 if (right_
->expr_type() == IVL_VT_REAL
)
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. */
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(),
242 ivl_variable_type_t
NetEBMult::expr_type() const
244 if (left_
->expr_type() == IVL_VT_REAL
)
247 if (right_
->expr_type() == IVL_VT_REAL
)
253 NetEBPow::NetEBPow(char op
, NetExpr
*l
, NetExpr
*r
)
254 : NetEBinary(op
, l
, r
)
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(),
269 result
->set_line(*this);
273 ivl_variable_type_t
NetEBPow::expr_type() const
275 if (right_
->expr_type() == IVL_VT_REAL
)
277 if (left_
->expr_type() == IVL_VT_REAL
)
279 if (left_
->has_sign())
281 if (right_
->has_sign())
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(),
312 NetEConcat::NetEConcat(unsigned cnt
, NetExpr
* r
)
313 : parms_(cnt
), repeat_(r
)
316 repeat_calculated_
= true;
319 repeat_calculated_
= false;
325 NetEConcat::~NetEConcat()
327 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1)
331 bool NetEConcat::has_width() const
336 void NetEConcat::set(unsigned idx
, NetExpr
*e
)
338 assert(idx
< parms_
.count());
339 assert(parms_
[idx
] == 0);
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)
349 NetExpr
*tmp
= parms_
[idx
]->dup_expr();
351 dup
->parms_
[idx
] = tmp
;
355 dup
->expr_width(expr_width());
359 unsigned NetEConcat::repeat()
361 if (repeat_calculated_
)
362 return repeat_value_
;
366 if (! dynamic_cast<NetEConst
*>(repeat_
)) {
367 NetExpr
*tmp
= repeat_
->eval_tree();
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: "
383 repeat_calculated_
= true;
388 repeat_calculated_
= true;
389 repeat_value_
= repeat_const
->value().as_ulong();
394 return repeat_value_
;
397 unsigned NetEConcat::repeat() const
399 assert(repeat_calculated_
);
400 return repeat_value_
;
403 NetECReal::NetECReal(const verireal
&val
)
408 NetECReal::~NetECReal()
412 const verireal
& NetECReal::value() const
417 bool NetECReal::has_width() const
422 NetECReal
* NetECReal::dup_expr() const
424 NetECReal
*tmp
= new NetECReal(value_
);
425 tmp
->set_line(*this);
429 ivl_variable_type_t
NetECReal::expr_type() const
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
448 const NetScope
* NetECRealParam::scope() const
454 NetEParam::NetEParam()
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
473 NetEParam
* NetEParam::dup_expr() const
475 NetEParam
*tmp
= new NetEParam(des_
, scope_
, name_
);
476 tmp
->set_line(*this);
480 NetESelect::NetESelect(NetExpr
*exp
, NetExpr
*base
, unsigned wid
)
481 : expr_(exp
), base_(base
)
486 NetESelect::~NetESelect()
492 const NetExpr
*NetESelect::sub_expr() const
497 const NetExpr
*NetESelect::select() const
502 bool NetESelect::has_width() const
507 NetESFunc::NetESFunc(const char*n
, ivl_variable_type_t t
,
508 unsigned width
, unsigned np
)
511 name_
= lex_strings
.add(n
);
514 parms_
= new NetExpr
*[np
];
515 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
519 NetESFunc::~NetESFunc()
521 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
522 if (parms_
[idx
]) delete parms_
[idx
];
525 /* name_ string ls lex_strings allocated. */
528 const char* NetESFunc::name() const
533 unsigned NetESFunc::nparms() const
538 void NetESFunc::parm(unsigned idx
, NetExpr
*v
)
540 assert(idx
< nparms_
);
546 const NetExpr
* NetESFunc::parm(unsigned idx
) const
548 assert(idx
< nparms_
);
552 NetExpr
* NetESFunc::parm(unsigned idx
)
554 assert(idx
< nparms_
);
558 ivl_variable_type_t
NetESFunc::expr_type() const
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
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
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
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