2 * Copyright (c) 1999-2006 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: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
28 * This file contains set_width methods for the various NetExpr
29 * classes. The set_width method is used by elaboration to ask the
30 * expression to resize itself. If the expression can't, then the
31 * set_width method will return false and the caller will arrange for
32 * whatever is needed to deal with the size mismatch.
36 # include "compiler.h"
40 bool NetExpr::set_width(unsigned w
, bool)
42 cerr
<< get_line() << ": internal warning: "
43 <<typeid(*this).name() << ": set_width(unsigned) "
44 << "not implemented." << endl
;
49 bool NetEBinary::set_width(unsigned w
, bool)
54 case 'l': // left shift (<<)
55 case 'r': // right shift (>>)
56 /* these operators are handled in the derived class. */
60 /* The default rule is that the operands of the binary
61 operator might as well use the same width as the
62 output from the binary operation. */
64 expr_width(left_
->expr_width() > right_
->expr_width()
65 ? left_
->expr_width() : right_
->expr_width());
66 cerr
<< "NetEBinary::set_width(): Using default for " <<
72 flag
= left_
->set_width(w
) && flag
;
73 flag
= right_
->set_width(w
) && flag
;
81 * The bitwise logical operators have operands the same size as the
82 * result. Anything else is a mess.
84 bool NetEBAdd::set_width(unsigned w
, bool)
88 if (left_
->expr_width() > wid
)
89 wid
= left_
->expr_width();
90 if (right_
->expr_width() > wid
)
91 wid
= right_
->expr_width();
93 left_
->set_width(wid
);
94 right_
->set_width(wid
);
96 if (left_
->expr_width() < wid
) {
97 NetExpr
*tmp
= new NetESelect(left_
, 0, wid
);
98 tmp
->cast_signed(left_
->has_sign());
102 if (right_
->expr_width() < wid
) {
103 NetExpr
*tmp
= new NetESelect(right_
, 0, wid
);
104 tmp
->cast_signed(right_
->has_sign());
113 * The bitwise logical operators have operands the same size as the
114 * result. Anything else is a mess. I first try to get the operands to
115 * shrink to the desired size. I then expand operands that are too small.
117 bool NetEBBits::set_width(unsigned w
, bool)
119 /* First, give the operands a chance to adjust themselves to
120 the requested width. */
122 right_
->set_width(w
);
127 unsigned use_width
= w
;
130 /* If the operands end up too small, then pad them to suit. */
132 if (left_
->expr_width() < use_width
) {
133 NetExpr
*tmp
= pad_to_width(left_
, use_width
);
138 if (right_
->expr_width() < w
) {
139 NetExpr
*tmp
= pad_to_width(right_
, use_width
);
145 /* And here is the final width. If this is not the size the
146 caller requested, then return false. Otherwise, return
148 expr_width(use_width
);
149 return w
== use_width
;
153 * Comparison operators allow the subexpressions to have
154 * their own natural width, but the comparison operator result has a
157 bool NetEBComp::set_width(unsigned w
, bool)
163 * There is nothing we can do to the operands of a division to make it
164 * confirm to the requested width. Force the context to pad or truncate.
166 bool NetEBDiv::set_width(unsigned w
, bool)
168 return w
== expr_width();
171 bool NetEBLogic::set_width(unsigned w
, bool)
174 flag
= left_
->set_width(right_
->expr_width());
176 flag
= right_
->set_width(left_
->expr_width());
181 * There is nothing we can do to the operands of a multiply to make it
182 * confirm to the requested width. Force the context to pad or truncate.
184 bool NetEBMult::set_width(unsigned w
, bool)
186 return w
== expr_width();
189 bool NetEBPow::set_width(unsigned w
, bool last_chance
)
191 bool flag
= left_
->set_width(w
, last_chance
);
196 * The shift operator allows the shift amount to have its own
197 * natural width. The width of the operator result is the width of the
198 * left operand, the value that is to be shifted.
200 bool NetEBShift::set_width(unsigned w
, bool)
208 if (left_
->expr_width() < w
)
209 left_
= pad_to_width(left_
, w
);
214 if (left_
->expr_width() < w
)
215 left_
= pad_to_width(left_
, w
);
222 expr_width(left_
->expr_width());
223 flag
= expr_width() == w
;
229 * Add up the widths from all the expressions that are concatenated
230 * together. This is the width of the expression, tough luck if you
233 * If during the course of elaboration one of the sub-expressions is
234 * broken, then don't count it in the width. This doesn't really
235 * matter because the null expression is indication of an error and
236 * the compiler will not go beyond elaboration.
238 bool NetEConcat::set_width(unsigned w
, bool)
241 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1)
242 if (parms_
[idx
] != 0)
243 sum
+= parms_
[idx
]->expr_width();
247 if (sum
!= w
) return false;
251 bool NetEConst::set_width(unsigned w
, bool last_chance
)
253 if (w
== value_
.len()) {
260 if (w
> value_
.len()) {
261 verinum::V pad
= verinum::V0
;
262 if (value_
.has_sign()) {
263 pad
= value_
.get(value_
.len()-1);
265 } else if (value_
.len() == 0) {
268 } else switch (value_
.get(value_
.len()-1)) {
280 verinum
tmp (verinum::V0
, w
, has_width());
281 for (unsigned idx
= 0 ; idx
< value_
.len() ; idx
+= 1)
282 tmp
.set(idx
, value_
[idx
]);
283 for (unsigned idx
= value_
.len() ; idx
< w
; idx
+= 1)
286 tmp
.has_sign(value_
.has_sign());
295 verinum::V pad_bit
= value_
.has_sign()
296 ? value_
[value_
.len() - 1]
300 // Don't reduce a number too small to hold all the
302 for (unsigned idx
= w
; idx
< value_
.len() ; idx
+= 1)
303 if (value_
[idx
] != pad_bit
)
306 // Correct for the special case of signed value. We
307 // cannot have the result change sign on us.
308 if (value_
.has_sign() && (use_w
< value_
.len())
309 && (value_
[use_w
-1] != pad_bit
))
313 verinum
tmp (verinum::V0
, use_w
, has_width());
314 for (unsigned idx
= 0 ; idx
< use_w
; idx
+= 1)
315 tmp
.set(idx
, value_
[idx
]);
317 tmp
.has_sign(value_
.has_sign());
325 * Parameter vectors cannot be resized because they refer to a common
328 bool NetEConstParam::set_width(unsigned w
, bool)
330 return w
== expr_width();
334 * Real constants can have whatever width the environment wants,
335 * because it isn't really a vector. The environment will convert this
336 * to a vector at the right time.
338 bool NetECReal::set_width(unsigned w
, bool)
344 bool NetEMemory::set_width(unsigned w
, bool)
346 if (w
!= mem_
->width())
353 bool NetEParam::set_width(unsigned, bool)
358 bool NetESelect::set_width(unsigned w
, bool)
360 if (expr_width() == 1)
366 bool NetESFunc::set_width(unsigned w
, bool)
368 return w
== expr_width();
372 * The signal should automatically pad with zeros to get to the desired
373 * width. Do not allow signal bits to be truncated, however.
375 bool NetESignal::set_width(unsigned w
, bool)
377 if (w
!= vector_width())
383 bool NetETernary::set_width(unsigned w
, bool last_chance
)
386 flag
= flag
&& true_val_
->set_width(w
, last_chance
);
387 flag
= flag
&& false_val_
->set_width(w
, last_chance
);
389 /* The ternary really insists that the true and false clauses
390 have the same width. Even if we fail to make the width that
391 the user requests, at least pad the smaller width to suit
393 if (true_val_
->expr_width() < false_val_
->expr_width())
394 true_val_
= pad_to_width(true_val_
, false_val_
->expr_width());
395 if (false_val_
->expr_width() < true_val_
->expr_width())
396 false_val_
= pad_to_width(false_val_
, true_val_
->expr_width());
398 expr_width(true_val_
->expr_width());
403 * XXXX FIX ME: For now, just take whatever the caller says as my
404 * width. What I really need to do is note the width of the output
405 * parameter of the function definition and take that into account.
407 bool NetEUFunc::set_width(unsigned wid
, bool)
413 bool NetEUnary::set_width(unsigned w
, bool)
419 flag
= expr_
->set_width(w
);
425 flag
= expr_width() == w
;
433 * Unary reduction operators allow its operand to have any width. The
434 * result is defined to be 1.
436 bool NetEUReduce::set_width(unsigned w
, bool)
443 * $Log: set_width.cc,v $
444 * Revision 1.42 2007/01/16 05:44:15 steve
445 * Major rework of array handling. Memories are replaced with the
446 * more general concept of arrays. The NetMemory and NetEMemory
447 * classes are removed from the ivl core program, and the IVL_LPM_RAM
448 * lpm type is removed from the ivl_target API.
450 * Revision 1.41 2006/11/04 06:19:25 steve
451 * Remove last bits of relax_width methods, and use test_width
452 * to calculate the width of an r-value expression that may
453 * contain unsized numbers.
455 * Revision 1.40 2006/10/30 05:44:49 steve
456 * Expression widths with unsized literals are pseudo-infinite width.
458 * Revision 1.39 2006/07/31 03:50:17 steve
459 * Add support for power in constant expressions.
461 * Revision 1.38 2006/05/02 04:29:42 steve
462 * Be more stubborn about widths.
464 * Revision 1.37 2005/11/26 00:35:44 steve
465 * More precise about r-value width of constants.
467 * Revision 1.36 2005/05/17 20:56:55 steve
468 * Parameters cannot have their width changed.
470 * Revision 1.35 2005/01/24 05:28:31 steve
471 * Remove the NetEBitSel and combine all bit/part select
472 * behavior into the NetESelect node and IVL_EX_SELECT
473 * ivl_target expression type.
475 * Revision 1.34 2003/08/28 04:11:19 steve
478 * Revision 1.33 2003/07/26 03:34:42 steve
479 * Start handling pad of expressions in code generators.
481 * Revision 1.32 2003/06/21 01:21:43 steve
482 * Harmless fixup of warnings.
484 * Revision 1.31 2003/06/18 03:55:19 steve
485 * Add arithmetic shift operators.
487 * Revision 1.30 2003/05/20 15:05:33 steve
488 * Do not try to set constants to width 0.
490 * Revision 1.29 2003/05/04 20:04:09 steve
491 * Fix truncation of signed constant in constant addition.
493 * Revision 1.28 2003/04/02 04:25:26 steve
494 * Fix xz extension of constants.
496 * Revision 1.27 2003/02/06 17:50:23 steve
497 * Real constants have no defined vector width
499 * Revision 1.26 2003/01/26 21:02:21 steve
500 * Remember to save signedness of number.
502 * Revision 1.25 2002/11/13 03:03:08 steve
503 * Do not truncate high bits of right shift.
505 * Revision 1.24 2002/11/06 02:25:13 steve
506 * No need to keep excess width from an
507 * unsigned constant value, if it can
510 * Revision 1.23 2002/08/12 01:35:00 steve
511 * conditional ident string using autoconfig.
513 * Revision 1.22 2002/05/05 21:11:50 steve
514 * Put off evaluation of concatenation repeat expresions
515 * until after parameters are defined. This allows parms
516 * to be used in repeat expresions.
518 * Add the builtin $signed system function.
520 * Revision 1.21 2002/04/27 04:49:27 steve
521 * If the verinum is already right, no need to reset it.
523 * Revision 1.20 2001/11/19 04:26:46 steve
524 * Unary reduction operators are all 1-bit results.
526 * Revision 1.19 2001/07/27 04:51:44 steve
527 * Handle part select expressions as variants of
528 * NetESignal/IVL_EX_SIGNAL objects, instead of
529 * creating new and useless temporary signals.
531 * Revision 1.18 2001/07/25 03:10:49 steve
532 * Create a config.h.in file to hold all the config
533 * junk, and support gcc 3.0. (Stephan Boettcher)
535 * Revision 1.17 2001/02/08 01:10:30 steve
538 * Revision 1.16 2001/02/07 21:47:13 steve
539 * Fix expression widths for rvalues and parameters (PR#131,132)
541 * Revision 1.15 2001/01/27 05:41:48 steve
542 * Fix sign extension of evaluated constants. (PR#91)
544 * Revision 1.14 2000/06/18 03:29:52 steve
545 * Handle width expansion of shift operators.
547 * Revision 1.13 2000/05/04 03:37:59 steve
548 * Add infrastructure for system functions, move
549 * $time to that structure and add $random.
551 * Revision 1.12 2000/04/28 18:43:23 steve
552 * integer division in expressions properly get width.
554 * Revision 1.11 2000/04/26 03:33:32 steve
555 * Do not set width too small to hold significant bits.
557 * Revision 1.10 2000/04/21 02:46:42 steve
558 * Many Unary operators have known widths.
560 * Revision 1.9 2000/02/23 02:56:55 steve
561 * Macintosh compilers do not support ident.
563 * Revision 1.8 2000/01/13 03:35:35 steve
564 * Multiplication all the way to simulation.
566 * Revision 1.7 2000/01/01 19:56:51 steve
567 * Properly expand/shrink constants in expressions.
569 * Revision 1.6 1999/10/05 06:19:46 steve
570 * Add support for reduction NOR.
572 * Revision 1.5 1999/10/05 04:02:10 steve
573 * Relaxed width handling for <= assignment.
575 * Revision 1.4 1999/09/29 00:42:51 steve
576 * Allow expanding of additive operators.
578 * Revision 1.3 1999/09/23 03:56:57 steve
579 * Support shift operators.
581 * Revision 1.2 1999/09/23 02:27:50 steve
582 * comparison parameter width is self determined.
584 * Revision 1.1 1999/09/23 00:21:55 steve
585 * Move set_width methods into a single file,
586 * Add the NetEBLogic class for logic expressions,
587 * Fix error setting with of && in if statements.