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 /* Make the value signed if the NetEConst is signed.
254 * This happens when $signed() is called, so this
255 * sign information needs to be propagated. */
256 value_
.has_sign(has_sign());
258 if (w
== value_
.len()) {
265 if (w
> value_
.len()) {
266 verinum::V pad
= verinum::V0
;
267 if (value_
.has_sign()) {
268 pad
= value_
.get(value_
.len()-1);
270 /* It appears that you always have a defined length here,
271 * so this logic may be in error. */
272 } else if (value_
.len() != 0 && !value_
.has_len())
273 switch (value_
.get(value_
.len()-1)) {
285 verinum
tmp (verinum::V0
, w
, has_width());
286 for (unsigned idx
= 0 ; idx
< value_
.len() ; idx
+= 1)
287 tmp
.set(idx
, value_
[idx
]);
288 for (unsigned idx
= value_
.len() ; idx
< w
; idx
+= 1)
291 tmp
.has_sign(value_
.has_sign());
300 verinum::V pad_bit
= value_
.has_sign()
301 ? value_
[value_
.len() - 1]
305 // Don't reduce a number too small to hold all the
307 for (unsigned idx
= w
; idx
< value_
.len() ; idx
+= 1)
308 if (value_
[idx
] != pad_bit
)
311 // Correct for the special case of signed value. We
312 // cannot have the result change sign on us.
313 if (value_
.has_sign() && (use_w
< value_
.len())
314 && (value_
[use_w
-1] != pad_bit
))
318 verinum
tmp (verinum::V0
, use_w
, has_width());
319 for (unsigned idx
= 0 ; idx
< use_w
; idx
+= 1)
320 tmp
.set(idx
, value_
[idx
]);
322 tmp
.has_sign(value_
.has_sign());
330 * Parameter vectors cannot be resized because they refer to a common
333 bool NetEConstParam::set_width(unsigned w
, bool)
335 return w
== expr_width();
339 * Real constants can have whatever width the environment wants,
340 * because it isn't really a vector. The environment will convert this
341 * to a vector at the right time.
343 bool NetECReal::set_width(unsigned w
, bool)
349 bool NetEMemory::set_width(unsigned w
, bool)
351 if (w
!= mem_
->width())
358 bool NetEParam::set_width(unsigned, bool)
363 bool NetESelect::set_width(unsigned w
, bool)
365 if (expr_width() == 1)
371 bool NetESFunc::set_width(unsigned w
, bool)
373 return w
== expr_width();
377 * The signal should automatically pad with zeros to get to the desired
378 * width. Do not allow signal bits to be truncated, however.
380 bool NetESignal::set_width(unsigned w
, bool)
382 if (w
!= vector_width())
388 bool NetETernary::set_width(unsigned w
, bool last_chance
)
391 flag
= flag
&& true_val_
->set_width(w
, last_chance
);
392 flag
= flag
&& false_val_
->set_width(w
, last_chance
);
394 /* The ternary really insists that the true and false clauses
395 have the same width. Even if we fail to make the width that
396 the user requests, at least pad the smaller width to suit
398 if (true_val_
->expr_width() < false_val_
->expr_width())
399 true_val_
= pad_to_width(true_val_
, false_val_
->expr_width());
400 if (false_val_
->expr_width() < true_val_
->expr_width())
401 false_val_
= pad_to_width(false_val_
, true_val_
->expr_width());
403 expr_width(true_val_
->expr_width());
408 * XXXX FIX ME: For now, just take whatever the caller says as my
409 * width. What I really need to do is note the width of the output
410 * parameter of the function definition and take that into account.
412 bool NetEUFunc::set_width(unsigned wid
, bool)
418 bool NetEUnary::set_width(unsigned w
, bool)
424 flag
= expr_
->set_width(w
);
430 flag
= expr_width() == w
;
438 * Unary reduction operators allow its operand to have any width. The
439 * result is defined to be 1.
441 bool NetEUReduce::set_width(unsigned w
, bool)