Implement $feof() from 1364-2005.
[iverilog.git] / net_expr.cc
blobee80713d83a0424362553e6eaed8c36c7bace081
1 /*
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)
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
20 # include "config.h"
21 # include "netlist.h"
22 # include "compiler.h"
23 # include <iostream>
26 * the grand default data type is a logic vector.
28 ivl_variable_type_t NetExpr::expr_type() const
30 return IVL_VT_LOGIC;
34 * Create an add/sub node from the two operands. Make a best guess of
35 * the
37 NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
38 : NetEBinary(op, l, r)
40 NetEConst* tmp;
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
46 possible result.
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);
90 } else {
91 expr_width(l->expr_width() + pad_width);
94 cast_signed(l->has_sign() && r->has_sign());
97 NetEBAdd::~NetEBAdd()
101 NetEBAdd* NetEBAdd::dup_expr() const
103 NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
104 right_->dup_expr());
105 return result;
108 ivl_variable_type_t NetEBAdd::expr_type() const
110 if (left_->expr_type() == IVL_VT_REAL)
111 return IVL_VT_REAL;
113 if (right_->expr_type() == IVL_VT_REAL)
114 return IVL_VT_REAL;
116 return IVL_VT_LOGIC;
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())
133 break;
135 if (l->expr_width() == 0)
136 break;
138 if (tmp->expr_width() == l->expr_width())
139 break;
141 tmp->set_width(l->expr_width());
143 } while (0);
145 if (NetEConst*tmp = dynamic_cast<NetEConst*>(l)) do {
147 if (tmp->has_width())
148 break;
150 if (r->expr_width() == 0)
151 break;
153 if (tmp->expr_width() == r->expr_width())
154 break;
156 tmp->set_width(r->expr_width());
158 } while (0);
161 expr_width(1);
164 NetEBComp::~NetEBComp()
168 bool NetEBComp::has_width() const
170 return true;
173 ivl_variable_type_t NetEBComp::expr_type() const
175 // Case compare always returns BOOL
176 if (op() == 'E' || op() == 'N')
177 return IVL_VT_BOOL;
179 if (left()->expr_type() == IVL_VT_LOGIC)
180 return IVL_VT_LOGIC;
182 if (right()->expr_type() == IVL_VT_LOGIC)
183 return IVL_VT_LOGIC;
185 return IVL_VT_BOOL;
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)
193 w = r->expr_width();
195 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(),
206 right_->dup_expr());
207 return result;
210 ivl_variable_type_t NetEBDiv::expr_type() const
212 if (left_->expr_type() == IVL_VT_REAL)
213 return IVL_VT_REAL;
215 if (right_->expr_type() == IVL_VT_REAL)
216 return IVL_VT_REAL;
218 return IVL_VT_LOGIC;
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. */
229 if (! has_sign()) {
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(),
242 right_->dup_expr());
243 return result;
246 ivl_variable_type_t NetEBMult::expr_type() const
248 if (left_->expr_type() == IVL_VT_REAL)
249 return IVL_VT_REAL;
251 if (right_->expr_type() == IVL_VT_REAL)
252 return IVL_VT_REAL;
254 return IVL_VT_LOGIC;
257 NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
258 : NetEBinary(op, l, r)
260 assert(op == 'p');
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(),
272 right_->dup_expr());
273 result->set_line(*this);
274 return result;
277 ivl_variable_type_t NetEBPow::expr_type() const
279 if (right_->expr_type() == IVL_VT_REAL)
280 return IVL_VT_REAL;
281 if (left_->expr_type() == IVL_VT_REAL)
282 return IVL_VT_REAL;
283 if (left_->has_sign())
284 return IVL_VT_REAL;
285 if (right_->has_sign())
286 return IVL_VT_REAL;
288 return IVL_VT_LOGIC;
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(),
312 right_->dup_expr());
313 return result;
316 NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
317 : parms_(cnt), repeat_(r)
319 if (repeat_ == 0) {
320 repeat_calculated_ = true;
321 repeat_value_ = 1;
322 } else {
323 repeat_calculated_ = false;
326 expr_width(0);
329 NetEConcat::~NetEConcat()
331 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
332 delete parms_[idx];
335 bool NetEConcat::has_width() const
337 return true;
340 void NetEConcat::set(unsigned idx, NetExpr*e)
342 assert(idx < parms_.count());
343 assert(parms_[idx] == 0);
344 parms_[idx] = e;
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)
352 if (parms_[idx]) {
353 NetExpr*tmp = parms_[idx]->dup_expr();
354 assert(tmp);
355 dup->parms_[idx] = tmp;
359 dup->expr_width(expr_width());
360 return dup;
363 unsigned NetEConcat::repeat()
365 if (repeat_calculated_)
366 return repeat_value_;
368 assert(repeat_);
370 if (! dynamic_cast<NetEConst*>(repeat_)) {
371 NetExpr*tmp = repeat_->eval_tree();
372 if (tmp != 0) {
373 delete repeat_;
374 repeat_ = tmp;
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: "
386 << *repeat_ << endl;
387 repeat_calculated_ = true;
388 repeat_value_ = 1;
389 return 1;
392 repeat_calculated_ = true;
393 repeat_value_ = repeat_const->value().as_ulong();
395 delete repeat_;
396 repeat_ = 0;
398 return repeat_value_;
401 unsigned NetEConcat::repeat() const
403 assert(repeat_calculated_);
404 return repeat_value_;
407 NetECReal::NetECReal(const verireal&val)
408 : value_(val)
410 expr_width(1);
413 NetECReal::~NetECReal()
417 const verireal& NetECReal::value() const
419 return value_;
422 bool NetECReal::has_width() const
424 return false;
427 NetECReal* NetECReal::dup_expr() const
429 NetECReal*tmp = new NetECReal(value_);
430 tmp->set_line(*this);
431 return tmp;
434 ivl_variable_type_t NetECReal::expr_type() const
436 return IVL_VT_REAL;
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
450 return name_;
453 const NetScope* NetECRealParam::scope() const
455 return scope_;
459 NetEParam::NetEParam()
460 : des_(0), scope_(0)
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
475 return false;
478 NetEParam* NetEParam::dup_expr() const
480 NetEParam*tmp = new NetEParam(des_, scope_, name_);
481 tmp->set_line(*this);
482 return tmp;
485 NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid)
486 : expr_(exp), base_(base)
488 expr_width(wid);
491 NetESelect::~NetESelect()
493 delete expr_;
494 delete base_;
497 const NetExpr*NetESelect::sub_expr() const
499 return expr_;
502 const NetExpr*NetESelect::select() const
504 return base_;
507 bool NetESelect::has_width() const
509 return true;
512 NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
513 unsigned width, unsigned np)
514 : name_(0), type_(t)
516 name_ = lex_strings.add(n);
517 expr_width(width);
518 nparms_ = np;
519 parms_ = new NetExpr*[np];
520 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
521 parms_[idx] = 0;
524 NetESFunc::~NetESFunc()
526 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
527 if (parms_[idx]) delete parms_[idx];
529 delete[]parms_;
530 /* name_ string ls lex_strings allocated. */
533 const char* NetESFunc::name() const
535 return name_;
538 unsigned NetESFunc::nparms() const
540 return nparms_;
543 void NetESFunc::parm(unsigned idx, NetExpr*v)
545 assert(idx < nparms_);
546 if (parms_[idx])
547 delete parms_[idx];
548 parms_[idx] = v;
551 const NetExpr* NetESFunc::parm(unsigned idx) const
553 assert(idx < nparms_);
554 return parms_[idx];
557 NetExpr* NetESFunc::parm(unsigned idx)
559 assert(idx < nparms_);
560 return parms_[idx];
563 ivl_variable_type_t NetESFunc::expr_type() const
565 return type_;