2 * Copyright (c) 2002-2007 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
22 # include "compiler.h"
26 * the grand default data type is a logic vector.
28 ivl_variable_type_t
NetExpr::expr_type() const
34 * Create an add/sub node from the two operands. Make a best guess of
37 NetEBAdd::NetEBAdd(char op
, NetExpr
*l
, NetExpr
*r
, bool lossless_flag
)
38 : NetEBinary(op
, l
, r
)
42 /* Catch the special case that one of the operands is an
43 unsized constant number. If so, then we should set the
44 width of that number to the size of the other operand, plus
45 one. This expands the expression to account for the largest
48 Remember to handle the special case of an unsized constant,
49 which we define to be at least "integer_width" bits.
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() || integer_width
> l
->expr_width()) ) {
58 unsigned target_width
= l
->expr_width() + 1;
59 if (target_width
< integer_width
)
60 target_width
= integer_width
;
61 r
->set_width(target_width
);
63 /* Note: This constant value will not gain a defined
64 width from this. Make sure. */
65 assert(! r
->has_width() );
67 } else if ( (tmp
= dynamic_cast<NetEConst
*>(l
))
68 && (! tmp
->has_width())
69 && (tmp
->expr_width() > r
->expr_width() || integer_width
> r
->expr_width()) ) {
71 unsigned target_width
= r
->expr_width() + 1;
72 if (target_width
< integer_width
)
73 target_width
= integer_width
;
74 l
->set_width(target_width
);
76 /* Note: This constant value will not gain a defined
77 width from this. Make sure. */
78 assert(! l
->has_width() );
82 unsigned pad_width
= lossless_flag
? 1 : 0;
84 /* Now that we have the operand sizes the way we like, or as
85 good as we are going to get them, set the size of myself. */
86 if (r
->expr_width() > l
->expr_width()) {
88 expr_width(r
->expr_width() + pad_width
);
91 expr_width(l
->expr_width() + pad_width
);
94 cast_signed(l
->has_sign() && r
->has_sign());
101 NetEBAdd
* NetEBAdd::dup_expr() const
103 NetEBAdd
*result
= new NetEBAdd(op_
, left_
->dup_expr(),
108 ivl_variable_type_t
NetEBAdd::expr_type() const
110 if (left_
->expr_type() == IVL_VT_REAL
)
113 if (right_
->expr_type() == IVL_VT_REAL
)
120 * Create a comparison operator with two sub-expressions.
122 * Handle the special case of an unsized constant on the left or right
123 * side by resizing the number to match the other
124 * expression. Otherwise, the netlist will have to allow the
125 * expressions to have different widths.
127 NetEBComp::NetEBComp(char op
, NetExpr
*l
, NetExpr
*r
)
128 : NetEBinary(op
, l
, r
)
130 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(r
)) do {
132 if (tmp
->has_width())
135 if (l
->expr_width() == 0)
138 if (tmp
->expr_width() == l
->expr_width())
141 tmp
->set_width(l
->expr_width());
145 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(l
)) do {
147 if (tmp
->has_width())
150 if (r
->expr_width() == 0)
153 if (tmp
->expr_width() == r
->expr_width())
156 tmp
->set_width(r
->expr_width());
164 NetEBComp::~NetEBComp()
168 bool NetEBComp::has_width() const
173 ivl_variable_type_t
NetEBComp::expr_type() const
175 // Case compare always returns BOOL
176 if (op() == 'E' || op() == 'N')
179 if (left()->expr_type() == IVL_VT_LOGIC
)
182 if (right()->expr_type() == IVL_VT_LOGIC
)
188 NetEBDiv::NetEBDiv(char op
, NetExpr
*l
, NetExpr
*r
)
189 : NetEBinary(op
, l
, r
)
191 unsigned w
= l
->expr_width();
192 if (r
->expr_width() > w
)
196 cast_signed(l
->has_sign() && r
->has_sign());
199 NetEBDiv::~NetEBDiv()
203 NetEBDiv
* NetEBDiv::dup_expr() const
205 NetEBDiv
*result
= new NetEBDiv(op_
, left_
->dup_expr(),
210 ivl_variable_type_t
NetEBDiv::expr_type() const
212 if (left_
->expr_type() == IVL_VT_REAL
)
215 if (right_
->expr_type() == IVL_VT_REAL
)
221 NetEBMult::NetEBMult(char op
, NetExpr
*l
, NetExpr
*r
)
222 : NetEBinary(op
, l
, r
)
224 expr_width(l
->expr_width() + r
->expr_width());
225 cast_signed(l
->has_sign() && r
->has_sign());
227 /* If it turns out that this is not a signed expression, then
228 cast the signedness out of the operands as well. */
230 l
->cast_signed(false);
231 r
->cast_signed(false);
235 NetEBMult::~NetEBMult()
239 NetEBMult
* NetEBMult::dup_expr() const
241 NetEBMult
*result
= new NetEBMult(op_
, left_
->dup_expr(),
246 ivl_variable_type_t
NetEBMult::expr_type() const
248 if (left_
->expr_type() == IVL_VT_REAL
)
251 if (right_
->expr_type() == IVL_VT_REAL
)
257 NetEBPow::NetEBPow(char op
, NetExpr
*l
, NetExpr
*r
)
258 : NetEBinary(op
, l
, r
)
261 expr_width(l
->expr_width());
262 cast_signed(l
->has_sign() || r
->has_sign());
265 NetEBPow::~NetEBPow()
269 NetEBPow
* NetEBPow::dup_expr() const
271 NetEBPow
*result
= new NetEBPow(op_
, left_
->dup_expr(),
273 result
->set_line(*this);
277 ivl_variable_type_t
NetEBPow::expr_type() const
279 if (right_
->expr_type() == IVL_VT_REAL
)
281 if (left_
->expr_type() == IVL_VT_REAL
)
283 if (left_
->has_sign())
285 if (right_
->has_sign())
291 NetEBShift::NetEBShift(char op
, NetExpr
*l
, NetExpr
*r
)
292 : NetEBinary(op
, l
, r
)
294 expr_width(l
->expr_width());
296 // The >>> is signed if the left operand is signed.
297 if (op
== 'R') cast_signed(l
->has_sign());
300 NetEBShift::~NetEBShift()
304 bool NetEBShift::has_width() const
306 return left_
->has_width();
309 NetEBShift
* NetEBShift::dup_expr() const
311 NetEBShift
*result
= new NetEBShift(op_
, left_
->dup_expr(),
316 NetEConcat::NetEConcat(unsigned cnt
, NetExpr
* r
)
317 : parms_(cnt
), repeat_(r
)
320 repeat_calculated_
= true;
323 repeat_calculated_
= false;
329 NetEConcat::~NetEConcat()
331 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1)
335 bool NetEConcat::has_width() const
340 void NetEConcat::set(unsigned idx
, NetExpr
*e
)
342 assert(idx
< parms_
.count());
343 assert(parms_
[idx
] == 0);
345 expr_width( expr_width() + e
->expr_width() );
348 NetEConcat
* NetEConcat::dup_expr() const
350 NetEConcat
*dup
= new NetEConcat(parms_
.count(), repeat_
);
351 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1)
353 NetExpr
*tmp
= parms_
[idx
]->dup_expr();
355 dup
->parms_
[idx
] = tmp
;
359 dup
->expr_width(expr_width());
363 unsigned NetEConcat::repeat()
365 if (repeat_calculated_
)
366 return repeat_value_
;
370 if (! dynamic_cast<NetEConst
*>(repeat_
)) {
371 NetExpr
*tmp
= repeat_
->eval_tree();
378 NetEConst
*repeat_const
= dynamic_cast<NetEConst
*>(repeat_
);
380 /* This should not be possible, as it was checked earlier to
381 assure that this is a constant expression. */
382 if (repeat_const
== 0) {
383 cerr
<< get_line() << ": internal error: repeat expression "
384 << "is not a compile time constant." << endl
;
385 cerr
<< get_line() << ": : Expression is: "
387 repeat_calculated_
= true;
392 repeat_calculated_
= true;
393 repeat_value_
= repeat_const
->value().as_ulong();
398 return repeat_value_
;
401 unsigned NetEConcat::repeat() const
403 assert(repeat_calculated_
);
404 return repeat_value_
;
407 NetECReal::NetECReal(const verireal
&val
)
413 NetECReal::~NetECReal()
417 const verireal
& NetECReal::value() const
422 bool NetECReal::has_width() const
427 NetECReal
* NetECReal::dup_expr() const
429 NetECReal
*tmp
= new NetECReal(value_
);
430 tmp
->set_line(*this);
434 ivl_variable_type_t
NetECReal::expr_type() const
439 NetECRealParam::NetECRealParam(NetScope
*s
, perm_string n
, const verireal
&v
)
440 : NetECReal(v
), scope_(s
), name_(n
)
444 NetECRealParam::~NetECRealParam()
448 perm_string
NetECRealParam::name() const
453 const NetScope
* NetECRealParam::scope() const
459 NetEParam::NetEParam()
464 NetEParam::NetEParam(Design
*d
, NetScope
*s
, perm_string n
)
465 : des_(d
), scope_(s
), name_(n
)
469 NetEParam::~NetEParam()
473 bool NetEParam::has_width() const
478 NetEParam
* NetEParam::dup_expr() const
480 NetEParam
*tmp
= new NetEParam(des_
, scope_
, name_
);
481 tmp
->set_line(*this);
485 NetESelect::NetESelect(NetExpr
*exp
, NetExpr
*base
, unsigned wid
)
486 : expr_(exp
), base_(base
)
491 NetESelect::~NetESelect()
497 const NetExpr
*NetESelect::sub_expr() const
502 const NetExpr
*NetESelect::select() const
507 bool NetESelect::has_width() const
512 NetESFunc::NetESFunc(const char*n
, ivl_variable_type_t t
,
513 unsigned width
, unsigned np
)
516 name_
= lex_strings
.add(n
);
519 parms_
= new NetExpr
*[np
];
520 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
524 NetESFunc::~NetESFunc()
526 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
527 if (parms_
[idx
]) delete parms_
[idx
];
530 /* name_ string ls lex_strings allocated. */
533 const char* NetESFunc::name() const
538 unsigned NetESFunc::nparms() const
543 void NetESFunc::parm(unsigned idx
, NetExpr
*v
)
545 assert(idx
< nparms_
);
551 const NetExpr
* NetESFunc::parm(unsigned idx
) const
553 assert(idx
< nparms_
);
557 NetExpr
* NetESFunc::parm(unsigned idx
)
559 assert(idx
< nparms_
);
563 ivl_variable_type_t
NetESFunc::expr_type() const