[PATCH] Implement System Verilog $urandom and $urandom_range functions.
[iverilog.git] / net_expr.cc
blob8c7be82a5393dc9d2d66c41a175eeaa2f66a470c
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 The set_width applied to a constant value will only
49 truncate the constant so far as it can still hold its
50 logical value, so this is safe to do. */
51 if ( (tmp = dynamic_cast<NetEConst*>(r))
52 && (! tmp->has_width())
53 && (tmp->expr_width() > l->expr_width()) ) {
55 unsigned target_width = l->expr_width() + 1;
56 r->set_width(target_width);
58 /* Note: This constant value will not gain a defined
59 width from this. Make sure. */
60 assert(! r->has_width() );
62 } else if ( (tmp = dynamic_cast<NetEConst*>(l))
63 && (! tmp->has_width())
64 && (tmp->expr_width() > r->expr_width()) ) {
66 unsigned target_width = r->expr_width() + 1;
67 l->set_width(target_width);
69 /* Note: This constant value will not gain a defined
70 width from this. Make sure. */
71 assert(! l->has_width() );
75 unsigned pad_width = lossless_flag? 1 : 0;
77 /* Now that we have the operand sizes the way we like, or as
78 good as we are going to get them, set the size of myself. */
79 if (r->expr_width() > l->expr_width()) {
81 expr_width(r->expr_width() + pad_width);
83 } else {
84 expr_width(l->expr_width() + pad_width);
87 cast_signed(l->has_sign() && r->has_sign());
90 NetEBAdd::~NetEBAdd()
94 NetEBAdd* NetEBAdd::dup_expr() const
96 NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(),
97 right_->dup_expr());
98 return result;
101 ivl_variable_type_t NetEBAdd::expr_type() const
103 if (left_->expr_type() == IVL_VT_REAL)
104 return IVL_VT_REAL;
106 if (right_->expr_type() == IVL_VT_REAL)
107 return IVL_VT_REAL;
109 return IVL_VT_LOGIC;
113 * Create a comparison operator with two sub-expressions.
115 * Handle the special case of an unsized constant on the left or right
116 * side by resizing the number to match the other
117 * expression. Otherwise, the netlist will have to allow the
118 * expressions to have different widths.
120 NetEBComp::NetEBComp(char op, NetExpr*l, NetExpr*r)
121 : NetEBinary(op, l, r)
123 if (NetEConst*tmp = dynamic_cast<NetEConst*>(r)) do {
125 if (tmp->has_width())
126 break;
128 if (l->expr_width() == 0)
129 break;
131 if (tmp->expr_width() == l->expr_width())
132 break;
134 tmp->set_width(l->expr_width());
136 } while (0);
138 if (NetEConst*tmp = dynamic_cast<NetEConst*>(l)) do {
140 if (tmp->has_width())
141 break;
143 if (r->expr_width() == 0)
144 break;
146 if (tmp->expr_width() == r->expr_width())
147 break;
149 tmp->set_width(r->expr_width());
151 } while (0);
154 expr_width(1);
157 NetEBComp::~NetEBComp()
161 bool NetEBComp::has_width() const
163 return true;
166 ivl_variable_type_t NetEBComp::expr_type() const
168 // Case compare always returns BOOL
169 if (op() == 'E' || op() == 'N')
170 return IVL_VT_BOOL;
172 if (left()->expr_type() == IVL_VT_LOGIC)
173 return IVL_VT_LOGIC;
175 if (right()->expr_type() == IVL_VT_LOGIC)
176 return IVL_VT_LOGIC;
178 return IVL_VT_BOOL;
181 NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
182 : NetEBinary(op, l, r)
184 unsigned w = l->expr_width();
185 if (r->expr_width() > w)
186 w = r->expr_width();
188 expr_width(w);
189 cast_signed(l->has_sign() && r->has_sign());
192 NetEBDiv::~NetEBDiv()
196 NetEBDiv* NetEBDiv::dup_expr() const
198 NetEBDiv*result = new NetEBDiv(op_, left_->dup_expr(),
199 right_->dup_expr());
200 return result;
203 ivl_variable_type_t NetEBDiv::expr_type() const
205 if (left_->expr_type() == IVL_VT_REAL)
206 return IVL_VT_REAL;
208 if (right_->expr_type() == IVL_VT_REAL)
209 return IVL_VT_REAL;
211 return IVL_VT_LOGIC;
214 NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
215 : NetEBinary(op, l, r)
217 expr_width(l->expr_width() + r->expr_width());
218 cast_signed(l->has_sign() && r->has_sign());
220 /* If it turns out that this is not a signed expression, then
221 cast the signedness out of the operands as well. */
222 if (! has_sign()) {
223 l->cast_signed(false);
224 r->cast_signed(false);
228 NetEBMult::~NetEBMult()
232 NetEBMult* NetEBMult::dup_expr() const
234 NetEBMult*result = new NetEBMult(op_, left_->dup_expr(),
235 right_->dup_expr());
236 return result;
239 ivl_variable_type_t NetEBMult::expr_type() const
241 if (left_->expr_type() == IVL_VT_REAL)
242 return IVL_VT_REAL;
244 if (right_->expr_type() == IVL_VT_REAL)
245 return IVL_VT_REAL;
247 return IVL_VT_LOGIC;
250 NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
251 : NetEBinary(op, l, r)
253 assert(op == 'p');
254 expr_width(l->expr_width());
255 cast_signed(l->has_sign() || r->has_sign());
258 NetEBPow::~NetEBPow()
262 NetEBPow* NetEBPow::dup_expr() const
264 NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
265 right_->dup_expr());
266 result->set_line(*this);
267 return result;
270 ivl_variable_type_t NetEBPow::expr_type() const
272 if (right_->expr_type() == IVL_VT_REAL)
273 return IVL_VT_REAL;
274 if (left_->expr_type() == IVL_VT_REAL)
275 return IVL_VT_REAL;
276 if (left_->has_sign())
277 return IVL_VT_REAL;
278 if (right_->has_sign())
279 return IVL_VT_REAL;
281 return IVL_VT_LOGIC;
284 NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
285 : NetEBinary(op, l, r)
287 expr_width(l->expr_width());
289 // The >>> is signed if the left operand is signed.
290 if (op == 'R') cast_signed(l->has_sign());
293 NetEBShift::~NetEBShift()
297 bool NetEBShift::has_width() const
299 return left_->has_width();
302 NetEBShift* NetEBShift::dup_expr() const
304 NetEBShift*result = new NetEBShift(op_, left_->dup_expr(),
305 right_->dup_expr());
306 return result;
309 NetEConcat::NetEConcat(unsigned cnt, NetExpr* r)
310 : parms_(cnt), repeat_(r)
312 if (repeat_ == 0) {
313 repeat_calculated_ = true;
314 repeat_value_ = 1;
315 } else {
316 repeat_calculated_ = false;
319 expr_width(0);
322 NetEConcat::~NetEConcat()
324 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
325 delete parms_[idx];
328 bool NetEConcat::has_width() const
330 return true;
333 void NetEConcat::set(unsigned idx, NetExpr*e)
335 assert(idx < parms_.count());
336 assert(parms_[idx] == 0);
337 parms_[idx] = e;
338 expr_width( expr_width() + e->expr_width() );
341 NetEConcat* NetEConcat::dup_expr() const
343 NetEConcat*dup = new NetEConcat(parms_.count(), repeat_);
344 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
345 if (parms_[idx]) {
346 NetExpr*tmp = parms_[idx]->dup_expr();
347 assert(tmp);
348 dup->parms_[idx] = tmp;
352 dup->expr_width(expr_width());
353 return dup;
356 unsigned NetEConcat::repeat()
358 if (repeat_calculated_)
359 return repeat_value_;
361 assert(repeat_);
363 if (! dynamic_cast<NetEConst*>(repeat_)) {
364 NetExpr*tmp = repeat_->eval_tree();
365 if (tmp != 0) {
366 delete repeat_;
367 repeat_ = tmp;
371 NetEConst*repeat_const = dynamic_cast<NetEConst*>(repeat_);
373 /* This should not be possible, as it was checked earlier to
374 assure that this is a constant expression. */
375 if (repeat_const == 0) {
376 cerr << get_line() << ": internal error: repeat expression "
377 << "is not a compile time constant." << endl;
378 cerr << get_line() << ": : Expression is: "
379 << *repeat_ << endl;
380 repeat_calculated_ = true;
381 repeat_value_ = 1;
382 return 1;
385 repeat_calculated_ = true;
386 repeat_value_ = repeat_const->value().as_ulong();
388 delete repeat_;
389 repeat_ = 0;
391 return repeat_value_;
394 unsigned NetEConcat::repeat() const
396 assert(repeat_calculated_);
397 return repeat_value_;
400 NetECReal::NetECReal(const verireal&val)
401 : value_(val)
403 expr_width(1);
406 NetECReal::~NetECReal()
410 const verireal& NetECReal::value() const
412 return value_;
415 bool NetECReal::has_width() const
417 return false;
420 NetECReal* NetECReal::dup_expr() const
422 NetECReal*tmp = new NetECReal(value_);
423 tmp->set_line(*this);
424 return tmp;
427 ivl_variable_type_t NetECReal::expr_type() const
429 return IVL_VT_REAL;
432 NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
433 : NetECReal(v), scope_(s), name_(n)
437 NetECRealParam::~NetECRealParam()
441 perm_string NetECRealParam::name() const
443 return name_;
446 const NetScope* NetECRealParam::scope() const
448 return scope_;
452 NetEParam::NetEParam()
453 : des_(0), scope_(0)
457 NetEParam::NetEParam(Design*d, NetScope*s, perm_string n)
458 : des_(d), scope_(s), name_(n)
462 NetEParam::~NetEParam()
466 bool NetEParam::has_width() const
468 return false;
471 NetEParam* NetEParam::dup_expr() const
473 NetEParam*tmp = new NetEParam(des_, scope_, name_);
474 tmp->set_line(*this);
475 return tmp;
478 NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid)
479 : expr_(exp), base_(base)
481 expr_width(wid);
484 NetESelect::~NetESelect()
486 delete expr_;
487 delete base_;
490 const NetExpr*NetESelect::sub_expr() const
492 return expr_;
495 const NetExpr*NetESelect::select() const
497 return base_;
500 bool NetESelect::has_width() const
502 return true;
505 NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
506 unsigned width, unsigned np)
507 : name_(0), type_(t)
509 name_ = lex_strings.add(n);
510 expr_width(width);
511 nparms_ = np;
512 parms_ = new NetExpr*[np];
513 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
514 parms_[idx] = 0;
517 NetESFunc::~NetESFunc()
519 for (unsigned idx = 0 ; idx < nparms_ ; idx += 1)
520 if (parms_[idx]) delete parms_[idx];
522 delete[]parms_;
523 /* name_ string ls lex_strings allocated. */
526 const char* NetESFunc::name() const
528 return name_;
531 unsigned NetESFunc::nparms() const
533 return nparms_;
536 void NetESFunc::parm(unsigned idx, NetExpr*v)
538 assert(idx < nparms_);
539 if (parms_[idx])
540 delete parms_[idx];
541 parms_[idx] = v;
544 const NetExpr* NetESFunc::parm(unsigned idx) const
546 assert(idx < nparms_);
547 return parms_[idx];
550 NetExpr* NetESFunc::parm(unsigned idx)
552 assert(idx < nparms_);
553 return parms_[idx];
556 ivl_variable_type_t NetESFunc::expr_type() const
558 return type_;