Implement $feof() from 1364-2005.
[iverilog.git] / set_width.cc
blobc47a2dad87ca217fa8f60984ef973c14cbe638e7
1 /*
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)
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
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.
34 # include "netlist.h"
35 # include "netmisc.h"
36 # include "compiler.h"
37 # include <typeinfo>
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;
45 expr_width(w);
46 return false;
49 bool NetEBinary::set_width(unsigned w, bool)
51 bool flag = true;
52 switch (op_) {
54 case 'l': // left shift (<<)
55 case 'r': // right shift (>>)
56 /* these operators are handled in the derived class. */
57 assert(0);
58 break;
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. */
63 default:
64 expr_width(left_->expr_width() > right_->expr_width()
65 ? left_->expr_width() : right_->expr_width());
66 cerr << "NetEBinary::set_width(): Using default for " <<
67 op_ << "." << endl;
68 flag = false;
70 case '%':
71 case '/':
72 flag = left_->set_width(w) && flag;
73 flag = right_->set_width(w) && flag;
74 expr_width(w);
75 break;
77 return 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)
87 unsigned wid = w;
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());
99 left_ = tmp;
102 if (right_->expr_width() < wid) {
103 NetExpr*tmp = new NetESelect(right_, 0, wid);
104 tmp->cast_signed(right_->has_sign());
105 right_ = tmp;
108 expr_width(wid);
109 return wid == w;
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. */
121 left_->set_width(w);
122 right_->set_width(w);
125 /* */
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);
134 assert(tmp);
135 left_ = tmp;
138 if (right_->expr_width() < w) {
139 NetExpr*tmp = pad_to_width(right_, use_width);
140 assert(tmp);
141 right_ = tmp;
145 /* And here is the final width. If this is not the size the
146 caller requested, then return false. Otherwise, return
147 true. */
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
155 * fixed width of 1.
157 bool NetEBComp::set_width(unsigned w, bool)
159 return (w == 1);
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)
173 bool flag;
174 flag = left_->set_width(right_->expr_width());
175 if (!flag)
176 flag = right_->set_width(left_->expr_width());
177 return (w == 1);
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);
192 return flag;
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)
202 bool flag = true;
204 switch (op()) {
206 case 'l':
207 left_->set_width(w);
208 if (left_->expr_width() < w)
209 left_ = pad_to_width(left_, w);
210 break;
212 case 'r':
213 case 'R':
214 if (left_->expr_width() < w)
215 left_ = pad_to_width(left_, w);
216 break;
218 default:
219 assert(0);
222 expr_width(left_->expr_width());
223 flag = expr_width() == w;
225 return flag;
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
231 * want it otherwise.
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)
240 unsigned sum = 0;
241 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
242 if (parms_[idx] != 0)
243 sum += parms_[idx]->expr_width();
245 sum *= repeat();
246 expr_width(sum);
247 if (sum != w) return false;
248 return true;
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()) {
259 expr_width(w);
260 return true;
263 assert(w != 0);
265 if (w > value_.len()) {
266 verinum::V pad = verinum::V0;
267 if (value_.has_sign()) {
268 pad = value_.get(value_.len()-1);
270 } else if (value_.len() == 0) {
271 pad = verinum::V0;
273 } else switch (value_.get(value_.len()-1)) {
274 case verinum::V1:
275 case verinum::V0:
276 break;
277 case verinum::Vx:
278 pad = verinum::Vx;
279 break;
280 case verinum::Vz:
281 pad = verinum::Vz;
282 break;
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)
289 tmp.set(idx, pad);
291 tmp.has_sign(value_.has_sign());
292 value_ = tmp;
294 expr_width(w);
295 return true;
297 } else {
298 unsigned use_w = w;
300 verinum::V pad_bit = value_.has_sign()
301 ? value_[value_.len() - 1]
302 : verinum::V0;
304 if (! last_chance) {
305 // Don't reduce a number too small to hold all the
306 // significant bits.
307 for (unsigned idx = w ; idx < value_.len() ; idx += 1)
308 if (value_[idx] != pad_bit)
309 use_w = idx+1;
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))
315 use_w += 1;
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());
323 value_ = tmp;
324 expr_width(use_w);
325 return use_w == w;
330 * Parameter vectors cannot be resized because they refer to a common
331 * value.
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)
345 expr_width(w);
346 return true;
348 #if 0
349 bool NetEMemory::set_width(unsigned w, bool)
351 if (w != mem_->width())
352 return false;
354 expr_width(w);
355 return true;
357 #endif
358 bool NetEParam::set_width(unsigned, bool)
360 return false;
363 bool NetESelect::set_width(unsigned w, bool)
365 if (expr_width() == 1)
366 return true;
367 else
368 return false;
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())
383 return false;
385 return true;
388 bool NetETernary::set_width(unsigned w, bool last_chance)
390 bool flag = true;
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
397 the larger. */
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());
404 return flag;
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)
414 expr_width(wid);
415 return true;
418 bool NetEUnary::set_width(unsigned w, bool)
420 bool flag = true;
421 switch (op_) {
422 case '~':
423 case '-':
424 flag = expr_->set_width(w);
425 expr_width(w);
426 break;
427 case '!':
428 return w == 1;
429 default:
430 flag = expr_width() == w;
431 break;
434 return flag;
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)
443 return w == 1;