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 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
);
84 expr_width(l
->expr_width() + pad_width
);
87 cast_signed(l
->has_sign() && r
->has_sign());
94 NetEBAdd
* NetEBAdd::dup_expr() const
96 NetEBAdd
*result
= new NetEBAdd(op_
, left_
->dup_expr(),
101 ivl_variable_type_t
NetEBAdd::expr_type() const
103 if (left_
->expr_type() == IVL_VT_REAL
)
106 if (right_
->expr_type() == IVL_VT_REAL
)
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())
128 if (l
->expr_width() == 0)
131 if (tmp
->expr_width() == l
->expr_width())
134 tmp
->set_width(l
->expr_width());
138 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(l
)) do {
140 if (tmp
->has_width())
143 if (r
->expr_width() == 0)
146 if (tmp
->expr_width() == r
->expr_width())
149 tmp
->set_width(r
->expr_width());
157 NetEBComp::~NetEBComp()
161 bool NetEBComp::has_width() const
166 ivl_variable_type_t
NetEBComp::expr_type() const
168 // Case compare always returns BOOL
169 if (op() == 'E' || op() == 'N')
172 if (left()->expr_type() == IVL_VT_LOGIC
)
175 if (right()->expr_type() == IVL_VT_LOGIC
)
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
)
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(),
203 ivl_variable_type_t
NetEBDiv::expr_type() const
205 if (left_
->expr_type() == IVL_VT_REAL
)
208 if (right_
->expr_type() == IVL_VT_REAL
)
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. */
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(),
239 ivl_variable_type_t
NetEBMult::expr_type() const
241 if (left_
->expr_type() == IVL_VT_REAL
)
244 if (right_
->expr_type() == IVL_VT_REAL
)
250 NetEBPow::NetEBPow(char op
, NetExpr
*l
, NetExpr
*r
)
251 : NetEBinary(op
, l
, r
)
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(),
266 result
->set_line(*this);
270 ivl_variable_type_t
NetEBPow::expr_type() const
272 if (right_
->expr_type() == IVL_VT_REAL
)
274 if (left_
->expr_type() == IVL_VT_REAL
)
276 if (left_
->has_sign())
278 if (right_
->has_sign())
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(),
309 NetEConcat::NetEConcat(unsigned cnt
, NetExpr
* r
)
310 : parms_(cnt
), repeat_(r
)
313 repeat_calculated_
= true;
316 repeat_calculated_
= false;
322 NetEConcat::~NetEConcat()
324 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1)
328 bool NetEConcat::has_width() const
333 void NetEConcat::set(unsigned idx
, NetExpr
*e
)
335 assert(idx
< parms_
.count());
336 assert(parms_
[idx
] == 0);
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)
346 NetExpr
*tmp
= parms_
[idx
]->dup_expr();
348 dup
->parms_
[idx
] = tmp
;
352 dup
->expr_width(expr_width());
356 unsigned NetEConcat::repeat()
358 if (repeat_calculated_
)
359 return repeat_value_
;
363 if (! dynamic_cast<NetEConst
*>(repeat_
)) {
364 NetExpr
*tmp
= repeat_
->eval_tree();
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: "
380 repeat_calculated_
= true;
385 repeat_calculated_
= true;
386 repeat_value_
= repeat_const
->value().as_ulong();
391 return repeat_value_
;
394 unsigned NetEConcat::repeat() const
396 assert(repeat_calculated_
);
397 return repeat_value_
;
400 NetECReal::NetECReal(const verireal
&val
)
406 NetECReal::~NetECReal()
410 const verireal
& NetECReal::value() const
415 bool NetECReal::has_width() const
420 NetECReal
* NetECReal::dup_expr() const
422 NetECReal
*tmp
= new NetECReal(value_
);
423 tmp
->set_line(*this);
427 ivl_variable_type_t
NetECReal::expr_type() const
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
446 const NetScope
* NetECRealParam::scope() const
452 NetEParam::NetEParam()
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
471 NetEParam
* NetEParam::dup_expr() const
473 NetEParam
*tmp
= new NetEParam(des_
, scope_
, name_
);
474 tmp
->set_line(*this);
478 NetESelect::NetESelect(NetExpr
*exp
, NetExpr
*base
, unsigned wid
)
479 : expr_(exp
), base_(base
)
484 NetESelect::~NetESelect()
490 const NetExpr
*NetESelect::sub_expr() const
495 const NetExpr
*NetESelect::select() const
500 bool NetESelect::has_width() const
505 NetESFunc::NetESFunc(const char*n
, ivl_variable_type_t t
,
506 unsigned width
, unsigned np
)
509 name_
= lex_strings
.add(n
);
512 parms_
= new NetExpr
*[np
];
513 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
517 NetESFunc::~NetESFunc()
519 for (unsigned idx
= 0 ; idx
< nparms_
; idx
+= 1)
520 if (parms_
[idx
]) delete parms_
[idx
];
523 /* name_ string ls lex_strings allocated. */
526 const char* NetESFunc::name() const
531 unsigned NetESFunc::nparms() const
536 void NetESFunc::parm(unsigned idx
, NetExpr
*v
)
538 assert(idx
< nparms_
);
544 const NetExpr
* NetESFunc::parm(unsigned idx
) const
546 assert(idx
< nparms_
);
550 NetExpr
* NetESFunc::parm(unsigned idx
)
552 assert(idx
< nparms_
);
556 ivl_variable_type_t
NetESFunc::expr_type() const