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