1 /*
2 * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
3 * Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
4 *
5 * This source code is free software; you can redistribute it
6 * and/or modify it in source code form under the terms of the GNU
7 * General Public License as published by the Free Software
8 * Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 # include "config.h"
22
23 # include "PExpr.h"
24 # include "netlist.h"
25 # include "netmisc.h"
26 # include "netstruct.h"
27 # include "netvector.h"
28 # include "compiler.h"
29
30 # include <cstdlib>
31 # include <cstring>
32 # include <iostream>
33 # include "ivl_assert.h"
34
35 /*
36 * The concatenation is also OK an an l-value. This method elaborates
37 * it as a structural l-value. The return values is the *input* net of
38 * the l-value, which may feed via part selects to the final
39 * destination. The caller can connect gate outputs to this signal to
40 * make the l-value connections.
41 */
elaborate_lnet_common_(Design * des,NetScope * scope,bool bidirectional_flag) const42 NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
43 bool bidirectional_flag) const
44 {
45 assert(scope);
46
47 svector<NetNet*>nets (parms_.size());
48 unsigned width = 0;
49 unsigned errors = 0;
50
51 if (repeat_) {
52 cerr << get_fileline() << ": sorry: I do not know how to"
53 " elaborate repeat concatenation nets." << endl;
54 return 0;
55 }
56
57 /* Elaborate the operands of the concatenation. */
58 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
59
60 if (debug_elaborate) {
61 cerr << get_fileline() << ": debug: Elaborate subexpression "
62 << idx << " of " << nets.count() << " l-values: "
63 << *parms_[idx] << endl;
64 }
65
66 if (parms_[idx] == 0) {
67 cerr << get_fileline() << ": error: Empty expressions "
68 << "not allowed in concatenations." << endl;
69 errors += 1;
70 continue;
71 }
72
73 if (bidirectional_flag) {
74 nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
75 } else {
76 nets[idx] = parms_[idx]->elaborate_lnet(des, scope);
77 }
78
79 if (nets[idx] == 0) {
80 errors += 1;
81 } else if (nets[idx]->data_type() == IVL_VT_REAL) {
82 cerr << parms_[idx]->get_fileline() << ": error: "
83 << "concatenation operand can no be real: "
84 << *parms_[idx] << endl;
85 errors += 1;
86 continue;
87 } else {
88 width += nets[idx]->vector_width();
89 }
90 }
91
92 if (errors) {
93 des->errors += errors;
94 return 0;
95 }
96
97 /* Make the temporary signal that connects to all the
98 operands, and connect it up. Scan the operands of the
99 concat operator from most significant to least significant,
100 which is the order they are given in the concat list. */
101
102 netvector_t*tmp2_vec = new netvector_t(nets[0]->data_type(),width-1,0);
103 NetNet*osig = new NetNet(scope, scope->local_symbol(),
104 NetNet::IMPLICIT, tmp2_vec);
105
106 /* Assume that the data types of the nets are all the same, so
107 we can take the data type of any, the first will do. */
108 osig->local_flag(true);
109 osig->set_line(*this);
110
111 if (bidirectional_flag) {
112 if (debug_elaborate) {
113 cerr << get_fileline() << ": debug: Generating tran(VP) "
114 << "to connect input l-value to subexpressions."
115 << endl;
116 }
117
118 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
119 unsigned wid = nets[idx]->vector_width();
120 unsigned off = width - wid;
121 NetTran*ps = new NetTran(scope, scope->local_symbol(),
122 osig->vector_width(), wid, off);
123 des->add_node(ps);
124 ps->set_line(*this);
125
126 connect(ps->pin(0), osig->pin(0));
127 connect(ps->pin(1), nets[idx]->pin(0));
128
129 ivl_assert(*this, wid <= width);
130 width -= wid;
131 }
132
133 } else {
134 if (debug_elaborate) {
135 cerr << get_fileline() << ": debug: Generating part selects "
136 << "to connect input l-value to subexpressions."
137 << endl;
138 }
139
140 NetPartSelect::dir_t part_dir = NetPartSelect::VP;
141
142 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
143 unsigned wid = nets[idx]->vector_width();
144 unsigned off = width - wid;
145 NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
146 des->add_node(ps);
147 ps->set_line(*this);
148
149 connect(ps->pin(1), osig->pin(0));
150 connect(ps->pin(0), nets[idx]->pin(0));
151
152 assert(wid <= width);
153 width -= wid;
154 }
155 assert(width == 0);
156 }
157
158 return osig;
159 }
160
elaborate_lnet(Design * des,NetScope * scope) const161 NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope) const
162 {
163 return elaborate_lnet_common_(des, scope, false);
164 }
165
elaborate_bi_net(Design * des,NetScope * scope) const166 NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
167 {
168 return elaborate_lnet_common_(des, scope, true);
169 }
170
is_collapsible_net(Design * des,NetScope * scope) const171 bool PEConcat::is_collapsible_net(Design*des, NetScope*scope) const
172 {
173 assert(scope);
174
175 // Repeat concatenations are not currently supported.
176 if (repeat_)
177 return false;
178
179 // Test the operands of the concatenation.
180 for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) {
181
182 // Empty expressions are not allowed in concatenations
183 if (parms_[idx] == 0)
184 return false;
185
186 if (!parms_[idx]->is_collapsible_net(des, scope))
187 return false;
188 }
189
190 return true;
191 }
192
193 /*
194 * This private method evaluates the part selects (if any) for the
195 * signal. The sig argument is the NetNet already located for the
196 * PEIdent name. The midx and lidx arguments are loaded with the
197 * results, which may be the whole vector, or a single bit, or
198 * anything in between. The values are in canonical indices.
199 */
eval_part_select_(Design * des,NetScope * scope,NetNet * sig,long & midx,long & lidx) const200 bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
201 long&midx, long&lidx) const
202 {
203 list<long> prefix_indices;
204 bool rc = calculate_packed_indices_(des, scope, sig, prefix_indices);
205 ivl_assert(*this, rc);
206
207 const name_component_t&name_tail = path_.back();
208 // Only treat as part/bit selects any index that is beyond the
209 // word selects for an array. This is not an array, then
210 // dimensions==0 and any index is treated as a select.
211 if (name_tail.index.size() <= sig->unpacked_dimensions()) {
212 midx = sig->vector_width()-1;
213 lidx = 0;
214 return true;
215 }
216
217 ivl_assert(*this, !name_tail.index.empty());
218
219 const index_component_t&index_tail = name_tail.index.back();
220
221 switch (index_tail.sel) {
222 default:
223 cerr << get_fileline() << ": internal error: "
224 << "Unexpected sel_ value = " << index_tail.sel << endl;
225 ivl_assert(*this, 0);
226 break;
227
228 case index_component_t::SEL_IDX_DO:
229 case index_component_t::SEL_IDX_UP: {
230 NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1, true);
231 NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
232 if (!tmp) {
233 cerr << get_fileline() << ": error: indexed part select of "
234 << sig->name()
235 << " must be a constant in this context." << endl;
236 des->errors += 1;
237 return 0;
238 }
239
240 /* The width (a constant) is calculated here. */
241 unsigned long wid = 0;
242 bool flag = calculate_up_do_width_(des, scope, wid);
243 if (! flag) return false;
244
245 /* We have an undefined index and that is out of range. */
246 if (! tmp->value().is_defined()) {
247 if (warn_ob_select) {
248 cerr << get_fileline() << ": warning: "
249 << sig->name();
250 if (sig->unpacked_dimensions() > 0) cerr << "[]";
251 cerr << "['bx";
252 if (index_tail.sel ==
253 index_component_t::SEL_IDX_UP) {
254 cerr << "+:";
255 } else {
256 cerr << "-:";
257 }
258 cerr << wid << "] is always outside the vector."
259 << endl;
260 }
261 return false;
262 }
263
264 long midx_val = tmp->value().as_long();
265 midx = sig->sb_to_idx(prefix_indices, midx_val);
266 delete tmp_ex;
267
268 if (index_tail.sel == index_component_t::SEL_IDX_UP)
269 lidx = sig->sb_to_idx(prefix_indices, midx_val+wid-1);
270 else
271 lidx = sig->sb_to_idx(prefix_indices, midx_val-wid+1);
272
273 if (midx < lidx) {
274 long tmpx = midx;
275 midx = lidx;
276 lidx = tmpx;
277 }
278
279 /* Warn about an indexed part select that is out of range. */
280 if (warn_ob_select && (lidx < 0)) {
281 cerr << get_fileline() << ": warning: " << sig->name();
282 if (sig->unpacked_dimensions() > 0) cerr << "[]";
283 cerr << "[" << midx_val;
284 if (index_tail.sel == index_component_t::SEL_IDX_UP) {
285 cerr << "+:";
286 } else {
287 cerr << "-:";
288 }
289 cerr << wid << "] is selecting before vector." << endl;
290 }
291 if (warn_ob_select && (midx >= (long)sig->vector_width())) {
292 cerr << get_fileline() << ": warning: " << sig->name();
293 if (sig->unpacked_dimensions() > 0) {
294 cerr << "[]";
295 }
296 cerr << "[" << midx_val;
297 if (index_tail.sel == index_component_t::SEL_IDX_UP) {
298 cerr << "+:";
299 } else {
300 cerr << "-:";
301 }
302 cerr << wid << "] is selecting after vector." << endl;
303 }
304
305 /* This is completely out side the signal so just skip it. */
306 if (lidx >= (long)sig->vector_width() || midx < 0) {
307 return false;
308 }
309
310 break;
311 }
312
313 case index_component_t::SEL_PART: {
314
315 long msb, lsb;
316 bool part_defined_flag;
317 /* bool flag = */ calculate_parts_(des, scope, msb, lsb, part_defined_flag);
318
319 /* We have an undefined index and that is out of range. */
320 if (!part_defined_flag) {
321 if (warn_ob_select) {
322 cerr << get_fileline() << ": warning: "
323 << sig->name();
324 if (sig->unpacked_dimensions() > 0) cerr << "[]";
325 cerr << "['bx] is always outside the vector."
326 << endl;
327 }
328 return false;
329 }
330
331 if (prefix_indices.size()+1 < sig->packed_dims().size()) {
332 // Here we have a slice that doesn't have enough indices
333 // to get to a single slice. For example:
334 // wire [9:0][5:1] foo
335 // ... foo[4:3] ...
336 // Make this work by finding the indexed slices and
337 // creating a generated slice that spans the whole
338 // range.
339 long loff, moff;
340 unsigned long lwid, mwid;
341 bool lrc;
342 lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
343 ivl_assert(*this, lrc);
344 lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
345 ivl_assert(*this, lrc);
346 ivl_assert(*this, lwid == mwid);
347
348 if (moff > loff) {
349 lidx = loff;
350 midx = moff + mwid - 1;
351 } else {
352 lidx = moff;
353 midx = loff + lwid - 1;
354 }
355 } else {
356 long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
357 long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
358
359 /* Detect reversed indices of a part select. */
360 if (lidx_tmp > midx_tmp) {
361 cerr << get_fileline() << ": error: Part select "
362 << sig->name() << "[" << msb << ":"
363 << lsb << "] indices reversed." << endl;
364 cerr << get_fileline() << ": : Did you mean "
365 << sig->name() << "[" << lsb << ":"
366 << msb << "]?" << endl;
367 long tmp = midx_tmp;
368 midx_tmp = lidx_tmp;
369 lidx_tmp = tmp;
370 des->errors += 1;
371 }
372
373 /* Warn about a part select that is out of range. */
374 if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
375 cerr << get_fileline() << ": warning: Part select "
376 << sig->name();
377 if (sig->unpacked_dimensions() > 0) {
378 cerr << "[]";
379 }
380 cerr << "[" << msb << ":" << lsb
381 << "] is out of range." << endl;
382 }
383 /* This is completely out side the signal so just skip it. */
384 if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
385 return false;
386 }
387
388 midx = midx_tmp;
389 lidx = lidx_tmp;
390 }
391 break;
392 }
393
394 case index_component_t::SEL_BIT:
395 if (name_tail.index.size() > sig->unpacked_dimensions()) {
396 long msb;
397 bool bit_defined_flag;
398 /* bool flag = */ calculate_bits_(des, scope, msb, bit_defined_flag);
399
400 /* We have an undefined index and that is out of range. */
401 if (!bit_defined_flag) {
402 if (warn_ob_select) {
403 cerr << get_fileline() << ": warning: "
404 << sig->name();
405 if (sig->unpacked_dimensions() > 0) cerr << "[]";
406 cerr << "['bx] is always outside the vector."
407 << endl;
408 }
409 return false;
410 }
411
412
413 if (prefix_indices.size()+2 <= sig->packed_dims().size()) {
414 long tmp_loff;
415 unsigned long tmp_lwid;
416 bool rcl = sig->sb_to_slice(prefix_indices, msb,
417 tmp_loff, tmp_lwid);
418 ivl_assert(*this, rcl);
419 midx = tmp_loff + tmp_lwid - 1;
420 lidx = tmp_loff;
421 } else {
422 midx = sig->sb_to_idx(prefix_indices, msb);
423 if (midx >= (long)sig->vector_width()) {
424 cerr << get_fileline() << ": error: Index " << sig->name()
425 << "[" << msb << "] is out of range."
426 << endl;
427 des->errors += 1;
428 midx = 0;
429 }
430 lidx = midx;
431 }
432
433 } else {
434 cerr << get_fileline() << ": internal error: "
435 << "Bit select " << path_ << endl;
436 ivl_assert(*this, 0);
437 midx = sig->vector_width() - 1;
438 lidx = 0;
439 }
440 break;
441 }
442
443 return true;
444 }
445
446 /*
447 * This is the common code for l-value nets and bi-directional
448 * nets. There is very little that is different between the two cases,
449 * so most of the work for both is done here.
450 */
elaborate_lnet_common_(Design * des,NetScope * scope,bool bidirectional_flag) const451 NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
452 bool bidirectional_flag) const
453 {
454 assert(scope);
455
456 NetNet* sig = 0;
457 const NetExpr*par = 0;
458 NetEvent* eve = 0;
459 perm_string method_name;
460
461 symbol_search(this, des, scope, path_, sig, par, eve);
462
463 if (eve != 0) {
464 cerr << get_fileline() << ": error: named events (" << path_
465 << ") cannot be l-values in continuous "
466 << "assignments." << endl;
467 des->errors += 1;
468 return 0;
469 }
470
471 // Break the path_ into the tail name and the prefix. For
472 // example, a name "a.b.c" is broken into name_tail="c" and
473 // path_prefix="a.b".
474 const name_component_t&path_tail = path_.back();
475 pform_name_t path_prefix = path_;
476 path_prefix.pop_back();
477
478 /* If the signal is not found, check to see if this is a
479 member of a struct. Take the name of the form "a.b.member",
480 remove the member and store it into method_name, and retry
481 the search with "a.b". */
482 if (sig == 0 && path_.size() >= 2) {
483 if (debug_elaborate) {
484 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
485 "Symbol not found, try again with path_prefix=" << path_prefix
486 << " and method_name=" << path_tail.name << endl;
487 }
488 method_name = path_tail.name;
489 symbol_search(this, des, scope, path_prefix, sig, par, eve);
490
491 // Whoops, not a struct signal, so give up on this avenue.
492 if (sig && sig->struct_type() == 0) {
493 cerr << get_fileline() << ": XXXXX: sig=" << sig->name()
494 << " is found, but not a struct with member " << method_name << endl;
495 method_name = perm_string();
496 sig = 0;
497 }
498 }
499
500 if (sig == 0) {
501 cerr << get_fileline() << ": error: Net " << path_
502 << " is not defined in this context." << endl;
503 des->errors += 1;
504 return 0;
505 }
506
507 assert(sig);
508
509 /* If this is SystemVerilog and the variable is not yet
510 assigned by anything, then convert it to an unresolved
511 wire. */
512 if (gn_var_can_be_uwire()
513 && (sig->type() == NetNet::REG)
514 && (sig->peek_lref() == 0) ) {
515 sig->type(NetNet::UNRESOLVED_WIRE);
516 }
517
518 /* Don't allow registers as assign l-values. */
519 if (sig->type() == NetNet::REG) {
520 cerr << get_fileline() << ": error: reg " << sig->name()
521 << "; cannot be driven by primitives"
522 << " or continuous assignment." << endl;
523 des->errors += 1;
524 return 0;
525 }
526
527 // Default part select is the entire word.
528 unsigned midx = sig->vector_width()-1, lidx = 0;
529 // The default word select is the first.
530 long widx = 0;
531 // Set this to true if we calculate the word index. This is
532 // used to distinguish between unpacked array assignment and
533 // array word assignment.
534 bool widx_flag = false;
535
536 list<long> unpacked_indices_const;
537
538 const netstruct_t*struct_type = 0;
539 if ((struct_type = sig->struct_type()) && !method_name.nil()) {
540
541 // Detect the variable is a structure and there was a
542 // method name detected. We've already found that
543 // the path_ is <>.sig.method_name and signal
544 // (NetNet). We also know that sig is struct_type(), so
545 // look for a method named method_name.
546 if (debug_elaborate)
547 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
548 << "Signal " << sig->name() << " is a structure, "
549 << "try to match member " << method_name << endl;
550
551 unsigned long member_off = 0;
552 const struct netstruct_t::member_t*member = struct_type->packed_member(method_name, member_off);
553 ivl_assert(*this, member);
554
555 if (debug_elaborate) {
556 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
557 << "Member " << method_name
558 << " has type " << *member->net_type << "." << endl;
559 cerr << get_fileline() << ": : "
560 << "Tail name has " << path_tail.index.size() << " indices." << endl;
561 }
562
563 // Rewrite a member select of a packed structure as a
564 // part select of the base variable.
565 lidx = member_off;
566 midx = lidx + member->net_type->packed_width() - 1;
567
568 // The dimensions of the tail of the prefix must match
569 // the dimensions of the signal at this point. (The sig
570 // has a packed dimension for the packed struct size.)
571 // For example, if the path_=a[<m>][<n>].member, then
572 // sig must have 3 packed dimensions: one for the struct
573 // members and two actual packed dimensions.
574 ivl_assert(*this, path_prefix.back().index.size()+1 == sig->packed_dimensions());
575
576 // Elaborate an expression from the packed indices and
577 // the member offset (into the structure) to get a
578 // canonical expression into the packed signal vector.
579 NetExpr*packed_base = 0;
580 if (sig->packed_dimensions() > 1) {
581 list<index_component_t>tmp_index = path_prefix.back().index;
582 index_component_t member_select;
583 member_select.sel = index_component_t::SEL_BIT;
584 member_select.msb = new PENumber(new verinum(member_off));
585 tmp_index.push_back(member_select);
586 packed_base = collapse_array_indices(des, scope, sig, tmp_index);
587
588 if (debug_elaborate) {
589 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
590 << "packed_base=" << *packed_base
591 << ", member_off=" << member_off << endl;
592 }
593 }
594
595 long tmp;
596 if (packed_base && eval_as_long(tmp, packed_base)) {
597 lidx = tmp;
598 midx = lidx + member->net_type->packed_width() - 1;
599 delete packed_base;
600 packed_base = 0;
601 }
602
603 // Currently, only support const dimensions here.
604 ivl_assert(*this, packed_base == 0);
605
606 // Now the lidx/midx values get us to the member. Next
607 // up, deal with bit/part selects from the member
608 // itself.
609 //XXXXivl_assert(*this, member->packed_dims.size() <= 1);
610 ivl_assert(*this, path_tail.index.size() <= 1);
611 if (! path_tail.index.empty()) {
612 long tmp_off;
613 unsigned long tmp_wid;
614 const index_component_t&tail_sel = path_tail.index.back();
615 ivl_assert(*this, tail_sel.sel == index_component_t::SEL_PART || tail_sel.sel == index_component_t::SEL_BIT);
616 bool rc = calculate_part(this, des, scope, tail_sel, tmp_off, tmp_wid);
617 ivl_assert(*this, rc);
618 if (debug_elaborate)
619 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
620 << "tmp_off=" << tmp_off << ", tmp_wid=" << tmp_wid << endl;
621 lidx += tmp_off;
622 midx = lidx + tmp_wid - 1;
623 }
624
625 } else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.empty()) {
626
627 // In this case, we are doing a continuous assignment to
628 // an unpacked array. The NetNet representation is a
629 // NetNet with a pin for each array element, so there is
630 // nothing more needed here.
631 //
632 // This can come up from code like this:
633 // logic [...] data [0:3];
634 // assign data = ...;
635 // In this case, "sig" is "data", and sig->pin_count()
636 // is 4 to account for the unpacked size.
637 if (debug_elaborate) {
638 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
639 << "Net assign to unpacked array \"" << sig->name()
640 << "\" with " << sig->pin_count() << " elements." << endl;
641 }
642
643 } else if (sig->unpacked_dimensions() > 0) {
644
645 // Make sure there are enough indices to address an array element.
646 if (path_tail.index.size() < sig->unpacked_dimensions()) {
647 cerr << get_fileline() << ": error: Array " << path()
648 << " needs " << sig->unpacked_dimensions() << " indices,"
649 << " but got only " << path_tail.index.size() << ". (net)" << endl;
650 des->errors += 1;
651 return 0;
652 }
653
654 // Evaluate all the index expressions into an
655 // "unpacked_indices" array.
656 list<NetExpr*>unpacked_indices;
657 indices_flags flags;
658 indices_to_expressions(des, scope, this,
659 path_tail.index, sig->unpacked_dimensions(),
660 true,
661 flags,
662 unpacked_indices,
663 unpacked_indices_const);
664
665 if (flags.invalid) {
666 return 0;
667
668 } else if (flags.variable) {
669 cerr << get_fileline() << ": error: array '" << sig->name()
670 << "' index must be a constant in this context." << endl;
671 des->errors += 1;
672 return 0;
673
674 } else if (flags.undefined) {
675 cerr << get_fileline() << ": warning: "
676 << "ignoring undefined l-value array access "
677 << sig->name() << as_indices(unpacked_indices)
678 << "." << endl;
679 widx = -1;
680 widx_flag = true;
681
682 } else {
683 NetExpr*canon_index = 0;
684 ivl_assert(*this, unpacked_indices_const.size() == sig->unpacked_dimensions());
685 canon_index = normalize_variable_unpacked(sig, unpacked_indices_const);
686
687 if (canon_index == 0) {
688 cerr << get_fileline() << ": warning: "
689 << "ignoring out of bounds l-value array access "
690 << sig->name() << as_indices(unpacked_indices_const)
691 << "." << endl;
692 widx = -1;
693 widx_flag = true;
694
695 } else {
696 NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
697 ivl_assert(*this, canon_const);
698
699 widx = canon_const->value().as_long();
700 widx_flag = true;
701 delete canon_index;
702 }
703 }
704
705 if (debug_elaborate)
706 cerr << get_fileline() << ": debug: Use [" << widx << "]"
707 << " to index l-value array." << endl;
708
709 /* The array has a part/bit select at the end. */
710 if (path_tail.index.size() > sig->unpacked_dimensions()) {
711 if (sig->get_scalar()) {
712 cerr << get_fileline() << ": error: "
713 << "can not select part of ";
714 if (sig->data_type() == IVL_VT_REAL) cerr << "real";
715 else cerr << "scalar";
716 cerr << " array word: " << sig->name()
717 << as_indices(unpacked_indices_const) << endl;
718 des->errors += 1;
719 return 0;
720 }
721
722 long midx_tmp, lidx_tmp;
723 if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
724 return 0;
725
726 if (lidx_tmp < 0) {
727 cerr << get_fileline() << ": sorry: part selects "
728 "straddling the start of signal (" << path_
729 << ") are not currently supported." << endl;
730 des->errors += 1;
731 return 0;
732 }
733 midx = midx_tmp;
734 lidx = lidx_tmp;
735 }
736
737 } else if (!path_tail.index.empty()) {
738 if (debug_elaborate) {
739 cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
740 << "path_tail.index.size()=" << path_tail.index.size()
741 << endl;
742 }
743
744 // There are index expressions on the name, so this is a
745 // bit/slice select of the name. Calculate a canonical
746 // part select.
747
748 if (sig->get_scalar()) {
749 cerr << get_fileline() << ": error: "
750 << "can not select part of ";
751 if (sig->data_type() == IVL_VT_REAL) cerr << "real: ";
752 else cerr << "scalar: ";
753 cerr << sig->name() << endl;
754 des->errors += 1;
755 return 0;
756 }
757
758 long midx_tmp, lidx_tmp;
759 if (! eval_part_select_(des, scope, sig, midx_tmp, lidx_tmp))
760 return 0;
761
762 if (lidx_tmp < 0) {
763 cerr << get_fileline() << ": sorry: part selects "
764 "straddling the start of signal (" << path_
765 << ") are not currently supported." << endl;
766 des->errors += 1;
767 return 0;
768 }
769 midx = midx_tmp;
770 lidx = lidx_tmp;
771 }
772
773 unsigned subnet_wid = midx-lidx+1;
774
775 /* Check if the l-value bits are double-driven. */
776 if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) {
777 cerr << get_fileline() << ": error: Unresolved net/uwire "
778 << sig->name() << " cannot have multiple drivers." << endl;
779 if (debug_elaborate) {
780 cerr << get_fileline() << ": : Overlap in "
781 << "[" << midx << ":" << lidx << "] (canonical)"
782 << ", widx=" << (widx_flag? widx : 0)
783 << ", vector width=" << sig->vector_width()
784 << endl;
785 }
786 des->errors += 1;
787 return 0;
788 }
789
790 if (sig->pin_count() > 1 && widx_flag) {
791 if (widx < 0 || widx >= (long) sig->pin_count())
792 return 0;
793
794 netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
795 sig->vector_width()-1,0);
796 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
797 sig->type(), tmp2_vec);
798 tmp->set_line(*this);
799 tmp->local_flag(true);
800 connect(sig->pin(widx), tmp->pin(0));
801 sig = tmp;
802
803 } else if (sig->pin_count() > 1) {
804
805 // If this turns out to be an l-value unpacked array,
806 // then let the caller handle it. It will probably be
807 // converted into an array of assignments.
808 return sig;
809 }
810
811 /* If the desired l-value vector is narrower than the
812 signal itself, then use a NetPartSelect node to
813 arrange for connection to the desired bits. All this
814 can be skipped if the desired width matches the
815 original vector. */
816
817 if (subnet_wid != sig->vector_width()) {
818 /* If we are processing a tran or inout, then the
819 partselect is bi-directional. Otherwise, it is a
820 Part-to-Vector select. */
821
822 if (debug_elaborate)
823 cerr << get_fileline() << ": debug: "
824 << "Elaborate lnet part select "
825 << sig->name()
826 << "[base=" << lidx
827 << " wid=" << subnet_wid <<"]"
828 << endl;
829
830 netvector_t*tmp2_vec = new netvector_t(sig->data_type(),
831 subnet_wid-1,0);
832 NetNet*subsig = new NetNet(sig->scope(),
833 sig->scope()->local_symbol(),
834 NetNet::WIRE, tmp2_vec);
835 subsig->local_flag(true);
836 subsig->set_line(*this);
837
838 if (bidirectional_flag) {
839 // Make a tran(VP)
840 NetTran*sub = new NetTran(scope, scope->local_symbol(),
841 sig->vector_width(),
842 subnet_wid, lidx);
843 sub->set_line(*this);
844 des->add_node(sub);
845 connect(sub->pin(0), sig->pin(0));
846 connect(sub->pin(1), subsig->pin(0));
847
848 } else {
849 NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
850 NetPartSelect::PV);
851 des->add_node(sub);
852 sub->set_line(*this);
853 connect(sub->pin(0), subsig->pin(0));
854 collapse_partselect_pv_to_concat(des, sig);
855 }
856 sig = subsig;
857 }
858
859 return sig;
860 }
861
862 /*
863 * Identifiers in continuous assignment l-values are limited to wires
864 * and that ilk. Detect registers and memories here and report errors.
865 */
elaborate_lnet(Design * des,NetScope * scope) const866 NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
867 {
868 return elaborate_lnet_common_(des, scope, false);
869 }
870
elaborate_bi_net(Design * des,NetScope * scope) const871 NetNet* PEIdent::elaborate_bi_net(Design*des, NetScope*scope) const
872 {
873 return elaborate_lnet_common_(des, scope, true);
874 }
875
876 /*
877 * This method is used to elaborate identifiers that are ports to a
878 * scope. The scope is presumed to be that of the module that has the
879 * port. This elaboration is done inside the module, and is only done
880 * to PEIdent objects. This method is used by elaboration of a module
881 * instantiation (PGModule::elaborate_mod_) to get NetNet objects for
882 * the port.
883 */
elaborate_subport(Design * des,NetScope * scope) const884 NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const
885 {
886 ivl_assert(*this, scope->type() == NetScope::MODULE);
887 NetNet*sig = des->find_signal(scope, path_);
888 if (sig == 0) {
889 cerr << get_fileline() << ": error: no wire/reg " << path_
890 << " in module " << scope_path(scope) << "." << endl;
891 des->errors += 1;
892 return 0;
893 }
894
895 /* Check the port_type of the signal to make sure it is really
896 a port, and its direction is resolved. */
897 switch (sig->port_type()) {
898 case NetNet::PINPUT:
899 case NetNet::POUTPUT:
900 case NetNet::PINOUT:
901 case NetNet::PREF:
902 break;
903
904 /* If the name matches, but the signal is not a port,
905 then the user declared the object but there is no
906 matching input/output/inout declaration. */
907
908 case NetNet::NOT_A_PORT:
909 cerr << get_fileline() << ": error: signal " << path_ << " in"
910 << " module " << scope_path(scope) << " is not a port." << endl;
911 cerr << get_fileline() << ": : Are you missing an input/"
912 << "output/inout declaration?" << endl;
913 des->errors += 1;
914 return 0;
915
916 /* This should not happen. A PWire can only become
917 PIMPLICIT if this is a UDP reg port, and the make_udp
918 function should turn it into an output.... I think. */
919
920 case NetNet::PIMPLICIT:
921 cerr << get_fileline() << ": internal error: signal " << path_
922 << " in module " << scope_path(scope) << " is left as "
923 << "port type PIMPLICIT." << endl;
924 des->errors += 1;
925 return 0;
926 }
927
928 long midx;
929 long lidx;
930
931 if (debug_elaborate) {
932 cerr << get_fileline() << ": PEIdent::elaborate_subport: "
933 << "path_ = \"" << path_
934 << "\", unpacked_dimensions=" << sig->unpacked_dimensions()
935 << ", port_type()=" << sig->port_type() << endl;
936 }
937
938 if (sig->unpacked_dimensions() && !gn_system_verilog()) {
939 cerr << get_fileline() << ": error: "
940 << "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl;
941 des->errors += 1;
942 return 0;
943 }
944
945 // There cannot be parts to an unpacked array, so process this
946 // simply as an unpacked array.
947 if (sig->unpacked_dimensions()) {
948 if (debug_elaborate) {
949 cerr << get_fileline() << ": PEIdent::elaborate_subport: "
950 << "path_=\"" << path_
951 << "\" is an unpacked array with " << sig->pin_count()
952 << " elements." << endl;
953 }
954 scope->add_module_port_net(sig);
955 return sig;
956 }
957
958 /* Evaluate the part/bit select expressions, to get the part
959 select of the signal that attaches to the port. Also handle
960 range and direction checking here. */
961
962 if (! eval_part_select_(des, scope, sig, midx, lidx))
963 return 0;
964
965 /* If this is a part select of the entire signal (or no part
966 select at all) then we're done. */
967 if ((lidx == 0) && (midx == (long)sig->vector_width()-1)) {
968 scope->add_module_port_net(sig);
969 return sig;
970 }
971
972 unsigned swid = abs(midx - lidx) + 1;
973 ivl_assert(*this, swid > 0 && swid < sig->vector_width());
974
975 netvector_t*tmp2_vec = new netvector_t(sig->data_type(),swid-1,0);
976 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
977 NetNet::WIRE, tmp2_vec);
978 tmp->port_type(sig->port_type());
979 tmp->set_line(*this);
980 tmp->local_flag(true);
981 NetNode*ps = 0;
982 switch (sig->port_type()) {
983
984 case NetNet::PINPUT:
985 ps = new NetPartSelect(sig, lidx, swid, NetPartSelect::PV);
986 connect(tmp->pin(0), ps->pin(0));
987 sig = tmp;
988 break;
989
990 case NetNet::POUTPUT:
991 ps = new NetPartSelect(sig, lidx, swid, NetPartSelect::VP);
992 connect(tmp->pin(0), ps->pin(0));
993 sig = tmp;
994 break;
995
996 case NetNet::PREF:
997 // For the purposes of module ports, treat ref ports
998 // just like inout ports.
999 case NetNet::PINOUT:
1000 ps = new NetTran(scope, scope->local_symbol(), sig->vector_width(),
1001 swid, lidx);
1002 connect(sig->pin(0), ps->pin(0));
1003 connect(tmp->pin(0), ps->pin(1));
1004 sig = tmp;
1005 break;
1006
1007 default:
1008 ivl_assert(*this, 0);
1009 break;
1010 }
1011
1012 ps->set_line(*this);
1013 des->add_node(ps);
1014
1015 scope->add_module_port_net(sig);
1016 return sig;
1017 }
1018
elaborate_unpacked_net(Design * des,NetScope * scope) const1019 NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const
1020 {
1021 NetNet* sig = 0;
1022 const NetExpr*par = 0;
1023 NetEvent* eve = 0;
1024 perm_string method_name;
1025
1026 symbol_search(this, des, scope, path_, sig, par, eve);
1027
1028 ivl_assert(*this, sig);
1029
1030 return sig;
1031 }
1032
is_collapsible_net(Design * des,NetScope * scope) const1033 bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const
1034 {
1035 assert(scope);
1036
1037 NetNet* sig = 0;
1038 const NetExpr*par = 0;
1039 NetEvent* eve = 0;
1040
1041 symbol_search(this, des, scope, path_, sig, par, eve);
1042
1043 if (eve != 0)
1044 return false;
1045
1046 if (sig == 0)
1047 return false;
1048
1049 assert(sig);
1050
1051 /* If this is SystemVerilog and the variable is not yet
1052 assigned by anything, then convert it to an unresolved
1053 wire. */
1054 if (gn_var_can_be_uwire()
1055 && (sig->type() == NetNet::REG)
1056 && (sig->peek_eref() == 0) ) {
1057 sig->type(NetNet::UNRESOLVED_WIRE);
1058 }
1059
1060 if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->pin(0).is_linked())
1061 return false;
1062
1063 if (sig->type() == NetNet::REG)
1064 return false;
1065
1066 return true;
1067 }
1068