Handle comments
[iverilog.git] / elab_lval.cc
blob517be81bb59ddc043029a762e48c78517b711072
1 /*
2 * Copyright (c) 2000-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: elab_lval.cc,v 1.44 2007/06/02 03:42:12 steve Exp $"
21 #endif
23 # include "config.h"
25 # include "PExpr.h"
26 # include "netlist.h"
27 # include "netmisc.h"
28 # include "compiler.h"
29 # include <iostream>
30 # include "ivl_assert.h"
33 * These methods generate a NetAssign_ object for the l-value of the
34 * assignment. This is common code for the = and <= statements.
36 * What gets generated depends on the structure of the l-value. If the
37 * l-value is a simple name (i.e., foo <= <value>) the the NetAssign_
38 * is created the width of the foo reg and connected to all the
39 * bits.
41 * If there is a part select (i.e., foo[3:1] <= <value>) the NetAssign_
42 * is made only as wide as it needs to be (3 bits in this example) and
43 * connected to the correct bits of foo. A constant bit select is a
44 * special case of the part select.
46 * If the bit-select is non-constant (i.e., foo[<expr>] = <value>) the
47 * NetAssign_ is made wide enough to connect to all the bits of foo,
48 * then the mux expression is elaborated and attached to the
49 * NetAssign_ node as a b_mux value. The target must interpret the
50 * presence of a bmux value as taking a single bit and assigning it to
51 * the bit selected by the bmux expression.
53 * If the l-value expression is non-trivial, but can be fully
54 * evaluated at compile time (meaning any bit selects are constant)
55 * then elaboration will make a single NetAssign_ that connects to a
56 * synthetic reg that in turn connects to all the proper pins of the
57 * l-value.
59 * This last case can turn up in statements like: {a, b[1]} = c;
60 * rather then create a NetAssign_ for each item in the concatenation,
61 * elaboration makes a single NetAssign_ and connects it up properly.
66 * The default interpretation of an l-value to a procedural assignment
67 * is to try to make a net elaboration, and see if the result is
68 * suitable for assignment.
70 NetAssign_* PExpr::elaborate_lval(Design*des,
71 NetScope*scope,
72 bool is_force) const
74 NetNet*ll = 0;
75 if (ll == 0) {
76 cerr << get_line() << ": Assignment l-value too complex."
77 << endl;
78 return 0;
81 NetAssign_*lv = new NetAssign_(ll);
82 return lv;
86 * Concatenation expressions can appear as l-values. Handle them here.
88 * If adjacent l-values in the concatenation are not bit selects, then
89 * merge them into a single NetAssign_ object. This can happen is code
90 * like ``{ ...a, b, ...}''. As long as "a" and "b" do not have bit
91 * selects (or the bit selects are constant) we can merge the
92 * NetAssign_ objects.
94 * Be careful to get the bit order right. In the expression ``{a, b}''
95 * a is the MSB and b the LSB. Connect the LSB to the low pins of the
96 * NetAssign_ object.
98 NetAssign_* PEConcat::elaborate_lval(Design*des,
99 NetScope*scope,
100 bool is_force) const
102 if (repeat_) {
103 cerr << get_line() << ": error: Repeat concatenations make "
104 "no sense in l-value expressions. I refuse." << endl;
105 des->errors += 1;
106 return 0;
109 NetAssign_*res = 0;
111 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
113 if (parms_[idx] == 0) {
114 cerr << get_line() << ": error: Empty expressions "
115 << "not allowed in concatenations." << endl;
116 des->errors += 1;
117 continue;
120 NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
122 /* If the l-value doesn't elaborate, the error was
123 already detected and printed. We just skip it and let
124 the compiler catch more errors. */
125 if (tmp == 0)
126 continue;
128 assert(tmp);
131 /* Link the new l-value to the previous one. */
133 NetAssign_*last = tmp;
134 while (last->more)
135 last = last->more;
137 last->more = res;
138 res = tmp;
141 return res;
145 * Handle the ident as an l-value. This includes bit and part selects
146 * of that ident.
148 NetAssign_* PEIdent::elaborate_lval(Design*des,
149 NetScope*scope,
150 bool is_force) const
152 NetNet* reg = 0;
153 const NetExpr*par = 0;
154 NetEvent* eve = 0;
156 symbol_search(des, scope, path_, reg, par, eve);
157 if (reg == 0) {
158 cerr << get_line() << ": error: Could not find variable ``"
159 << path_ << "'' in ``" << scope_path(scope) <<
160 "''" << endl;
162 des->errors += 1;
163 return 0;
166 ivl_assert(*this, reg);
168 const name_component_t&name_tail = path_.back();
170 index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
171 if (!name_tail.index.empty())
172 use_sel = name_tail.index.back().sel;
174 // This is the special case that the l-value is an entire
175 // memory. This is, in fact, an error.
176 if (reg->array_dimensions() > 0 && name_tail.index.empty()) {
177 cerr << get_line() << ": error: Cannot assign to array "
178 << path_ << ". Did you forget a word index?" << endl;
179 des->errors += 1;
180 return 0;
183 if (reg->array_dimensions() > 0)
184 return elaborate_lval_net_word_(des, scope, reg);
186 if (use_sel == index_component_t::SEL_PART) {
187 NetAssign_*lv = new NetAssign_(reg);
188 elaborate_lval_net_part_(des, scope, lv);
189 return lv;
192 if (use_sel == index_component_t::SEL_IDX_UP ||
193 use_sel == index_component_t::SEL_IDX_DO) {
194 NetAssign_*lv = new NetAssign_(reg);
195 elaborate_lval_net_idx_(des, scope, lv, use_sel);
196 return lv;
199 /* Get the signal referenced by the identifier, and make sure
200 it is a register. Wires are not allows in this context,
201 unless this is the l-value of a force. */
202 if ((reg->type() != NetNet::REG) && !is_force) {
203 cerr << get_line() << ": error: " << path_ <<
204 " is not a valid l-value in " << scope_path(scope) <<
205 "." << endl;
206 cerr << reg->get_line() << ": : " << path_ <<
207 " is declared here as " << reg->type() << "." << endl;
208 des->errors += 1;
209 return 0;
212 long msb, lsb;
213 NetExpr*mux;
215 if (use_sel == index_component_t::SEL_BIT) {
217 const index_component_t&index_tail = name_tail.index.back();
218 ivl_assert(*this, index_tail.msb != 0);
219 ivl_assert(*this, index_tail.lsb == 0);
221 /* If there is only a single select expression, it is a
222 bit select. Evaluate the constant value and treat it
223 as a part select with a bit width of 1. If the
224 expression it not constant, then return the
225 expression as a mux. */
227 NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
229 if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
230 msb = index_con->value().as_long();
231 lsb = index_con->value().as_long();
232 mux = 0;
234 } else {
235 msb = 0;
236 lsb = 0;
237 mux = index_expr;
240 } else {
242 /* No select expressions, so presume a part select the
243 width of the register. */
245 msb = reg->msb();
246 lsb = reg->lsb();
247 mux = 0;
251 NetAssign_*lv;
252 if (mux) {
254 /* If there is a non-constant bit select, make a
255 NetAssign_ to the target reg and attach a
256 bmux to select the target bit. */
257 lv = new NetAssign_(reg);
259 /* Correct the mux for the range of the vector. */
260 if (reg->msb() < reg->lsb())
261 mux = make_sub_expr(reg->lsb(), mux);
262 else if (reg->lsb() != 0)
263 mux = make_add_expr(mux, - reg->lsb());
265 lv->set_part(mux, 1);
267 } else if (msb == reg->msb() && lsb == reg->lsb()) {
269 /* No bit select, and part select covers the entire
270 vector. Simplest case. */
271 lv = new NetAssign_(reg);
273 } else {
275 /* If the bit/part select is constant, then make the
276 NetAssign_ only as wide as it needs to be and connect
277 only to the selected bits of the reg. */
278 unsigned loff = reg->sb_to_idx(lsb);
279 unsigned moff = reg->sb_to_idx(msb);
280 unsigned wid = moff - loff + 1;
282 if (moff < loff) {
283 cerr << get_line() << ": error: part select "
284 << reg->name() << "[" << msb<<":"<<lsb<<"]"
285 << " is reversed." << endl;
286 des->errors += 1;
287 return 0;
290 /* If the part select extends beyond the extreme of the
291 variable, then report an error. Note that loff is
292 converted to normalized form so is relative the
293 variable pins. */
295 if ((wid + loff) > reg->vector_width()) {
296 cerr << get_line() << ": error: bit/part select "
297 << reg->name() << "[" << msb<<":"<<lsb<<"]"
298 << " is out of range." << endl;
299 des->errors += 1;
300 return 0;
303 lv = new NetAssign_(reg);
304 lv->set_part(new NetEConst(verinum(loff)), wid);
308 return lv;
311 NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
312 NetScope*scope,
313 NetNet*reg) const
315 const name_component_t&name_tail = path_.back();
316 ivl_assert(*this, !name_tail.index.empty());
318 const index_component_t&index_head = name_tail.index.front();
319 if (index_head.sel == index_component_t::SEL_PART) {
320 cerr << get_line() << ": error: cannot perform a part "
321 << "select on array " << reg->name() << "." << endl;
322 des->errors += 1;
323 return 0;
326 ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
327 ivl_assert(*this, index_head.msb != 0);
328 ivl_assert(*this, index_head.lsb == 0);
330 NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
332 // If there is a non-zero base to the memory, then build an
333 // expression to calculate the canonical address.
334 if (long base = reg->array_first()) {
336 word = make_add_expr(word, 0-base);
337 if (NetExpr*tmp = word->eval_tree()) {
338 word = tmp;
342 NetAssign_*lv = new NetAssign_(reg);
343 lv->set_word(word);
345 if (debug_elaborate)
346 cerr << get_line() << ": debug: Set array word=" << *word << endl;
348 // Test for the case that the index is a constant, and is out
349 // of bounds. The "word" expression is the word index already
350 // converted to canonical address, so this just needs to check
351 // that the address is not too big.
352 if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
353 verinum word_val = word_const->value();
354 long index = word_val.as_long();
355 if (index < 0 || index >= reg->array_count()) {
356 cerr << get_line() << ": warning: Constant array index "
357 << (index + reg->array_first())
358 << " is out of range for array "
359 << reg->name() << "." << endl;
363 /* An array word may also have part selects applied to them. */
365 index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
366 if (name_tail.index.size() > 1)
367 use_sel = name_tail.index.back().sel;
369 if (use_sel == index_component_t::SEL_PART)
370 elaborate_lval_net_part_(des, scope, lv);
372 if (use_sel == index_component_t::SEL_IDX_UP ||
373 use_sel == index_component_t::SEL_IDX_DO)
374 elaborate_lval_net_idx_(des, scope, lv, use_sel);
376 return lv;
379 bool PEIdent::elaborate_lval_net_part_(Design*des,
380 NetScope*scope,
381 NetAssign_*lv) const
383 long msb, lsb;
384 bool flag = calculate_parts_(des, scope, msb, lsb);
385 if (!flag)
386 return false;
388 NetNet*reg = lv->sig();
389 assert(reg);
391 if (msb == reg->msb() && lsb == reg->lsb()) {
393 /* No bit select, and part select covers the entire
394 vector. Simplest case. */
396 } else {
398 /* If the bit/part select is constant, then make the
399 NetAssign_ only as wide as it needs to be and connect
400 only to the selected bits of the reg. */
401 unsigned loff = reg->sb_to_idx(lsb);
402 unsigned moff = reg->sb_to_idx(msb);
403 unsigned wid = moff - loff + 1;
405 if (moff < loff) {
406 cerr << get_line() << ": error: part select "
407 << reg->name() << "[" << msb<<":"<<lsb<<"]"
408 << " is reversed." << endl;
409 des->errors += 1;
410 return false;
413 /* If the part select extends beyond the extreme of the
414 variable, then report an error. Note that loff is
415 converted to normalized form so is relative the
416 variable pins. */
418 if ((wid + loff) > reg->vector_width()) {
419 cerr << get_line() << ": error: bit/part select "
420 << reg->name() << "[" << msb<<":"<<lsb<<"]"
421 << " is out of range." << endl;
422 des->errors += 1;
423 return false;
426 lv->set_part(new NetEConst(verinum(loff)), wid);
429 return true;
432 bool PEIdent::elaborate_lval_net_idx_(Design*des,
433 NetScope*scope,
434 NetAssign_*lv,
435 index_component_t::ctype_t use_sel) const
437 const name_component_t&name_tail = path_.back();;
438 ivl_assert(*this, !name_tail.index.empty());
440 const index_component_t&index_tail = name_tail.index.back();
441 ivl_assert(*this, index_tail.msb != 0);
442 ivl_assert(*this, index_tail.lsb != 0);
444 NetNet*reg = lv->sig();
445 assert(reg);
447 if (reg->type() != NetNet::REG) {
448 cerr << get_line() << ": error: " << path_ <<
449 " is not a reg/integer/time in " << scope_path(scope) <<
450 "." << endl;
451 cerr << reg->get_line() << ": : " << path_ <<
452 " is declared here as " << reg->type() << "." << endl;
453 des->errors += 1;
454 return false;
457 unsigned long wid;
458 calculate_up_do_width_(des, scope, wid);
460 NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
462 /* Correct the mux for the range of the vector. */
463 if (reg->msb() < reg->lsb())
464 base = make_sub_expr(reg->lsb(), base);
465 else if (reg->lsb() != 0)
466 base = make_add_expr(base, - reg->lsb());
468 if (use_sel == index_component_t::SEL_IDX_DO && wid > 1 ) {
469 base = make_add_expr(base, 1-(long)wid);
472 if (debug_elaborate)
473 cerr << get_line() << ": debug: Set part select width="
474 << wid << ", base=" << *base << endl;
476 lv->set_part(base, wid);
478 return true;
481 NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
483 cerr << get_line() << ": error: Constant values not allowed "
484 << "in l-value expressions." << endl;
485 des->errors += 1;
486 return 0;