2 * Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 #ident "$Id: elab_net.cc,v 1.207 2007/06/12 04:05:45 steve Exp $"
28 # include "compiler.h"
31 # include "ivl_assert.h"
34 * This is a state flag that determines whether an elaborate_net must
35 * report an error when it encounters an unsized number. Normally, it
36 * is fine to make an unsized number as small as it can be, but there
37 * are a few cases where the size must be fully self-determined. For
38 * example, within a {...} (concatenation) operator.
40 static bool must_be_self_determined_flag
= false;
42 NetNet
* PExpr::elaborate_net(Design
*des
, NetScope
*scope
, unsigned,
47 Link::strength_t
) const
49 cerr
<< get_line() << ": error: Unable to elaborate `"
50 << *this << "' as gates." << endl
;
55 * Elaborating binary operations generally involves elaborating the
56 * left and right expressions, then making an output wire and
57 * connecting the lot together with the right kind of gate.
59 NetNet
* PEBinary::elaborate_net(Design
*des
, NetScope
*scope
,
64 Link::strength_t drive0
,
65 Link::strength_t drive1
) const
69 return elaborate_net_mul_(des
, scope
, width
, rise
, fall
, decay
);
71 return elaborate_net_mod_(des
, scope
, width
, rise
, fall
, decay
);
73 return elaborate_net_div_(des
, scope
, width
, rise
, fall
, decay
);
76 return elaborate_net_add_(des
, scope
, width
, rise
, fall
, decay
);
77 case '|': // Bitwise OR
80 case 'A': // Bitwise NAND (~&)
81 case 'O': // Bitwise NOR (~|)
82 case 'X': // Exclusive NOR
83 return elaborate_net_bit_(des
, scope
, width
, rise
, fall
, decay
);
84 case 'E': // === (case equals)
86 case 'N': // !== (case not-equals)
92 return elaborate_net_cmp_(des
, scope
, width
, rise
, fall
, decay
);
93 case 'a': // && (logical and)
94 case 'o': // || (logical or)
95 return elaborate_net_log_(des
, scope
, width
, rise
, fall
, decay
);
99 return elaborate_net_shift_(des
, scope
, width
, rise
, fall
, decay
);
102 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, width
, 0, 0, 0),
103 *rsig
= right_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
105 cerr
<< get_line() << ": error: Cannot elaborate ";
111 cerr
<< get_line() << ": error: Cannot elaborate ";
123 case '|': // Bitwise OR
127 case 'E': // === (Case equals)
147 cerr
<< get_line() << ": internal error: unsupported"
148 " combinational operator (" << op_
<< ")." << endl
;
157 * Elaborate the structural +/- as an AddSub object. Connect DataA and
158 * DataB to the parameters, and connect the output signal to the
159 * Result. In this context, the device is a combinational adder with
160 * fixed direction, so leave Add_Sub unconnected and set the
161 * LPM_Direction property.
163 NetNet
* PEBinary::elaborate_net_add_(Design
*des
, NetScope
*scope
,
167 const NetExpr
* decay
) const
169 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0),
170 *rsig
= right_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
172 cerr
<< get_line() << ": error: Cannot elaborate ";
178 cerr
<< get_line() << ": error: Cannot elaborate ";
186 unsigned width
= lsig
->vector_width();
187 if (rsig
->vector_width() > lsig
->vector_width())
188 width
= rsig
->vector_width();
191 /* The owidth is the output width of the lpm_add_sub
192 device. If the desired width is greater then the width of
193 the operands, then widen the adder and let code below pad
195 unsigned owidth
= width
;
198 if (lwidth
> owidth
) {
204 if (lwidth
> owidth
) {
213 bool expr_signed
= lsig
->get_signed() && rsig
->get_signed();
215 // Pad out the operands, if necessary, the match the width of
217 if (lsig
->vector_width() < width
)
219 lsig
= pad_to_width_signed(des
, lsig
, width
);
221 lsig
= pad_to_width(des
, lsig
, width
);
223 if (rsig
->vector_width() < width
)
225 rsig
= pad_to_width_signed(des
, rsig
, width
);
227 rsig
= pad_to_width(des
, rsig
, width
);
229 // Check that the argument types match.
230 if (lsig
->data_type() != rsig
->data_type()) {
231 cerr
<< get_line() << ": error: Arguments of add/sub "
232 << "have different data types." << endl
;
233 cerr
<< get_line() << ": : Left argument is "
234 << lsig
->data_type() << ", right argument is "
235 << rsig
->data_type() << "." << endl
;
239 // Make the adder as wide as the widest operand
240 osig
= new NetNet(scope
, scope
->local_symbol(),
241 NetNet::WIRE
, owidth
);
242 osig
->data_type(lsig
->data_type());
243 osig
->set_signed(expr_signed
);
244 osig
->local_flag(true);
245 if (debug_elaborate
) {
246 cerr
<< get_line() << ": debug: Elaborate NetAddSub "
247 << "width=" << width
<< " lwidth=" << lwidth
250 NetAddSub
*adder
= new NetAddSub(scope
, scope
->local_symbol(), width
);
252 // Connect the adder to the various parts.
253 connect(lsig
->pin(0), adder
->pin_DataA());
254 connect(rsig
->pin(0), adder
->pin_DataB());
255 connect(osig
->pin(0), adder
->pin_Result());
258 connect(osig
->pin(width
), adder
->pin_Cout());
260 NetNode
*gate
= adder
;
261 gate
->rise_time(rise
);
262 gate
->fall_time(fall
);
263 gate
->decay_time(decay
);
266 gate
->attribute(perm_string::literal("LPM_Direction"),
267 verinum(op_
== '+' ? "ADD" : "SUB"));
273 * Elaborate various bitwise logic operators. These are all similar in
274 * that they take operants of equal width, and each bit does not
275 * affect any other bits. Also common about all this is how bit widths
276 * of the operands are handled, when they do not match.
278 NetNet
* PEBinary::elaborate_net_bit_(Design
*des
, NetScope
*scope
,
282 const NetExpr
* decay
) const
284 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, width
, 0, 0, 0),
285 *rsig
= right_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
287 cerr
<< get_line() << ": error: Cannot elaborate ";
293 cerr
<< get_line() << ": error: Cannot elaborate ";
299 if (lsig
->vector_width() < rsig
->vector_width())
300 lsig
= pad_to_width(des
, lsig
, rsig
->vector_width());
301 if (rsig
->vector_width() < lsig
->vector_width())
302 rsig
= pad_to_width(des
, rsig
, lsig
->vector_width());
304 if (lsig
->data_type() != rsig
->data_type()) {
305 cerr
<< get_line() << ": error: Types of "
306 << "operands of " << op_
<< " do not match: "
307 << lsig
->data_type() << " vs. " << rsig
->data_type()
313 if (lsig
->vector_width() != rsig
->vector_width()) {
314 cerr
<< get_line() << ": internal error: lsig width ("
315 << lsig
->vector_width() << ") != rsig pin width ("
316 << rsig
->vector_width() << ")." << endl
;
321 assert(lsig
->vector_width() == rsig
->vector_width());
323 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
,
324 lsig
->vector_width());
325 osig
->local_flag(true);
326 osig
->data_type( lsig
->data_type() );
328 NetLogic::TYPE gtype
=NetLogic::AND
;
330 case '^': gtype
= NetLogic::XOR
; break; // XOR
331 case 'X': gtype
= NetLogic::XNOR
; break; // XNOR
332 case '&': gtype
= NetLogic::AND
; break; // AND
333 case 'A': gtype
= NetLogic::NAND
; break; // NAND (~&)
334 case '|': gtype
= NetLogic::OR
; break; // Bitwise OR
335 case 'O': gtype
= NetLogic::NOR
; break; // Bitwise NOR
339 NetLogic
*gate
= new NetLogic(scope
, scope
->local_symbol(),
340 3, gtype
, osig
->vector_width());
341 gate
->set_line(*this);
342 connect(gate
->pin(0), osig
->pin(0));
343 connect(gate
->pin(1), lsig
->pin(0));
344 connect(gate
->pin(2), rsig
->pin(0));
345 gate
->rise_time(rise
);
346 gate
->fall_time(fall
);
347 gate
->decay_time(decay
);
354 * This function attempts to handle the special case of == or !=
355 * compare to a constant value. The caller has determined already that
356 * one of the operands is a NetEConst, and has already elaborated the
359 static NetNet
* compare_eq_constant(Design
*des
, NetScope
*scope
,
360 NetNet
*lsig
, NetEConst
*rexp
,
364 const NetExpr
* decay
)
366 if (op_code
!= 'e' && op_code
!= 'n')
369 verinum val
= rexp
->value();
371 /* Abandon special case if there are x or z bits in the
372 constant. We can't get the right behavior out of
373 OR/NOR in this case. */
374 if (! val
.is_defined())
377 if (val
.len() < lsig
->vector_width())
378 val
= verinum(val
, lsig
->vector_width());
380 /* Look for the very special case that we know the compare
381 results a priori due to different high bits, that are
382 constant pad in the signal. */
383 if (val
.len() > lsig
->vector_width()) {
384 unsigned idx
= lsig
->vector_width();
385 verinum::V lpad
= verinum::V0
;
387 while (idx
< val
.len()) {
388 if (val
.get(idx
) != lpad
) {
389 verinum
oval (op_code
== 'e'
393 NetEConst
*ogate
= new NetEConst(oval
);
394 NetNet
*osig
= ogate
->synthesize(des
);
395 osig
->data_type(lsig
->data_type());
399 cerr
<< lsig
->get_line() << ": debug: "
400 << "Equality replaced with "
401 << oval
<< " due to high pad mismatch"
413 for (unsigned idx
= 0 ; idx
< lsig
->vector_width() ; idx
+= 1) {
414 if (val
.get(idx
) == verinum::V0
)
416 if (val
.get(idx
) == verinum::V1
)
420 /* Handle the special case that the gate is a compare that can
421 be replaces with a reduction AND or NOR. */
423 if (ones
== 0 || zeros
== 0) {
424 NetUReduce::TYPE type
;
427 type
= op_code
== 'e'? NetUReduce::NOR
: NetUReduce::OR
;
430 cerr
<< lsig
->get_line() << ": debug: "
431 << "Replace net==" << val
<< " equality with "
432 << zeros
<< "-input reduction [N]OR gate." << endl
;
435 type
= op_code
== 'e'? NetUReduce::AND
: NetUReduce::NAND
;
438 cerr
<< lsig
->get_line() << ": debug: "
439 << "Replace net==" << val
<< " equality with "
440 << ones
<< "-input reduction AND gate." << endl
;
443 NetUReduce
*red
= new NetUReduce(scope
, scope
->local_symbol(),
446 red
->set_line(*lsig
);
448 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
450 tmp
->data_type(lsig
->data_type());
451 tmp
->local_flag(true);
452 tmp
->set_line(*lsig
);
454 connect(red
->pin(1), lsig
->pin(0));
455 connect(red
->pin(0), tmp
->pin(0));
460 cerr
<< lsig
->get_line() << ": debug: "
461 << "Give up trying to replace net==" << val
463 << ones
<< "-input AND and "
464 << zeros
<< "-input NOR gates." << endl
;
470 * Elaborate the various binary comparison operators. The comparison
471 * operators return a single bit result, no matter what, so the left
472 * and right values can have their own size. The only restriction is
473 * that they have the same size.
475 NetNet
* PEBinary::elaborate_net_cmp_(Design
*des
, NetScope
*scope
,
479 const NetExpr
* decay
) const
482 /* Elaborate the operands of the compare first as expressions
483 (so that the eval_tree method can reduce constant
484 expressions, including parameters) then turn those results
485 into synthesized nets. */
486 NetExpr
*lexp
= elab_and_eval(des
, scope
, left_
, lwidth
);
488 cerr
<< get_line() << ": error: Cannot elaborate ";
494 NetExpr
*rexp
= elab_and_eval(des
, scope
, right_
, lwidth
);
496 cerr
<< get_line() << ": error: Cannot elaborate ";
502 /* Choose the operand width to be the width of the widest
503 self-determined operand. */
504 unsigned operand_width
= lexp
->expr_width();
505 if (rexp
->expr_width() > operand_width
)
506 operand_width
= rexp
->expr_width();
508 lexp
->set_width(operand_width
);
509 lexp
= pad_to_width(lexp
, operand_width
);
510 rexp
->set_width(operand_width
);
511 rexp
= pad_to_width(rexp
, operand_width
);
516 /* Handle the special case that the right or left
517 sub-expression is a constant value. The compare_eq_constant
518 function will return an elaborated result if it can make
519 use of the situation, or 0 if it cannot. */
520 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(rexp
)) {
522 lsig
= lexp
->synthesize(des
);
524 cerr
<< get_line() << ": internal error: "
525 "Cannot elaborate net for " << *lexp
<< endl
;
532 NetNet
*osig
= compare_eq_constant(des
, scope
,
541 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(lexp
)) {
543 rsig
= rexp
->synthesize(des
);
547 NetNet
*osig
= compare_eq_constant(des
, scope
,
557 lsig
= lexp
->synthesize(des
);
563 rsig
= rexp
->synthesize(des
);
568 unsigned dwidth
= lsig
->vector_width();
569 if (rsig
->vector_width() > dwidth
) dwidth
= rsig
->vector_width();
571 /* Operands of binary compare need to be padded to equal
572 size. Figure the pad bit needed to extend the narrowest
574 if (lsig
->vector_width() < dwidth
)
575 lsig
= pad_to_width(des
, lsig
, dwidth
);
576 if (rsig
->vector_width() < dwidth
)
577 rsig
= pad_to_width(des
, rsig
, dwidth
);
580 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
);
581 osig
->data_type(IVL_VT_LOGIC
);
582 osig
->set_line(*this);
583 osig
->local_flag(true);
593 NetCompare(scope
, scope
->local_symbol(), dwidth
);
594 connect(cmp
->pin_DataA(), lsig
->pin(0));
595 connect(cmp
->pin_DataB(), rsig
->pin(0));
599 connect(cmp
->pin_ALB(), osig
->pin(0));
602 connect(cmp
->pin_AGB(), osig
->pin(0));
605 connect(cmp
->pin_ALEB(), osig
->pin(0));
608 connect(cmp
->pin_AGEB(), osig
->pin(0));
611 /* If both operands are signed, then do a signed
613 if (lsig
->get_signed() && rsig
->get_signed())
614 cmp
->set_signed(true);
620 case 'E': // Case equals (===)
621 gate
= new NetCaseCmp(scope
, scope
->local_symbol(), dwidth
, true);
622 connect(gate
->pin(0), osig
->pin(0));
623 connect(gate
->pin(1), lsig
->pin(0));
624 connect(gate
->pin(2), rsig
->pin(0));
627 case 'N': // Case equals (!==)
628 gate
= new NetCaseCmp(scope
, scope
->local_symbol(), dwidth
, false);
629 connect(gate
->pin(0), osig
->pin(0));
630 connect(gate
->pin(1), lsig
->pin(0));
631 connect(gate
->pin(2), rsig
->pin(0));
636 /* Handle the special case of single bit compare with a
637 single XNOR gate. This is easy and direct. */
639 gate
= new NetLogic(scope
, scope
->local_symbol(),
640 3, NetLogic::XNOR
, 1);
641 connect(gate
->pin(0), osig
->pin(0));
642 connect(gate
->pin(1), lsig
->pin(0));
643 connect(gate
->pin(2), rsig
->pin(0));
647 if (debug_elaborate
) {
648 cerr
<< get_line() << ": debug: Elaborate net == gate."
652 /* Oh well, do the general case with a NetCompare. */
653 { NetCompare
*cmp
= new NetCompare(scope
, scope
->local_symbol(),
655 connect(cmp
->pin_DataA(), lsig
->pin(0));
656 connect(cmp
->pin_DataB(), rsig
->pin(0));
657 connect(cmp
->pin_AEB(), osig
->pin(0));
664 /* Handle the special case of single bit compare with a
665 single XOR gate. This is easy and direct. */
667 gate
= new NetLogic(scope
, scope
->local_symbol(),
668 3, NetLogic::XOR
, 1);
669 connect(gate
->pin(0), osig
->pin(0));
670 connect(gate
->pin(1), lsig
->pin(0));
671 connect(gate
->pin(2), rsig
->pin(0));
675 /* Oh well, do the general case with a NetCompare. */
676 { NetCompare
*cmp
= new NetCompare(scope
, scope
->local_symbol(),
678 connect(cmp
->pin_DataA(), lsig
->pin(0));
679 connect(cmp
->pin_DataB(), rsig
->pin(0));
680 connect(cmp
->pin_ANEB(), osig
->pin(0));
689 gate
->rise_time(rise
);
690 gate
->fall_time(fall
);
691 gate
->decay_time(decay
);
698 * Elaborate a divider gate. This function create a NetDivide gate
699 * which has exactly the right sized DataA, DataB and Result ports. If
700 * the l-value is wider then the result, then pad.
702 NetNet
* PEBinary::elaborate_net_div_(Design
*des
, NetScope
*scope
,
706 const NetExpr
* decay
) const
708 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
709 if (lsig
== 0) return 0;
710 NetNet
*rsig
= right_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
711 if (rsig
== 0) return 0;
714 // Check the l-value width. If it is unspecified, then use the
715 // largest operand width as the l-value width. Restrict the
716 // result width to the width of the largest operand, because
717 // there is no value is excess divider.
719 unsigned rwidth
= lwidth
;
722 rwidth
= lsig
->vector_width();
723 if (rsig
->vector_width() > rwidth
)
724 rwidth
= rsig
->vector_width();
729 if ((rwidth
> lsig
->vector_width()) && (rwidth
> rsig
->vector_width())) {
730 rwidth
= lsig
->vector_width();
731 if (rsig
->vector_width() > rwidth
)
732 rwidth
= rsig
->vector_width();
735 /* The arguments of a divide must have the same type. */
736 if (lsig
->data_type() != rsig
->data_type()) {
737 cerr
<< get_line() << ": error: Arguments of divide "
738 << "have different data types." << endl
;
739 cerr
<< get_line() << ": : Left argument is "
740 << lsig
->data_type() << ", right argument is "
741 << rsig
->data_type() << "." << endl
;
745 ivl_variable_type_t data_type
= lsig
->data_type();
747 // Create a device with the calculated dimensions.
748 NetDivide
*div
= new NetDivide(scope
, scope
->local_symbol(), rwidth
,
749 lsig
->vector_width(),
750 rsig
->vector_width());
753 div
->set_signed(lsig
->get_signed() && rsig
->get_signed());
755 // Connect the left and right inputs of the divider to the
756 // nets that are the left and right expressions.
758 connect(div
->pin_DataA(), lsig
->pin(0));
759 connect(div
->pin_DataB(), rsig
->pin(0));
762 // Make an output signal that is the width of the l-value.
763 // Due to above calculation of rwidth, we know that the result
764 // will be no more than the l-value, so it is safe to connect
765 // all the result pins to the osig.
767 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
768 NetNet::IMPLICIT
, lwidth
);
769 osig
->local_flag(true);
770 osig
->data_type(data_type
);
771 osig
->set_signed(div
->get_signed());
773 connect(div
->pin_Result(), osig
->pin(0));
780 * Elaborate a modulo gate.
782 NetNet
* PEBinary::elaborate_net_mod_(Design
*des
, NetScope
*scope
,
786 const NetExpr
* decay
) const
788 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
789 if (lsig
== 0) return 0;
790 NetNet
*rsig
= right_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
791 if (rsig
== 0) return 0;
793 /* The arguments of a modulus must have the same type. */
794 if (lsig
->data_type() != rsig
->data_type()) {
795 cerr
<< get_line() << ": error: Arguments of modulus "
796 << "have different data types." << endl
;
797 cerr
<< get_line() << ": : Left argument is "
798 << lsig
->data_type() << ", right argument is "
799 << rsig
->data_type() << "." << endl
;
803 ivl_variable_type_t data_type
= lsig
->data_type();
805 /* rwidth is result width. */
806 unsigned rwidth
= lwidth
;
808 rwidth
= lsig
->vector_width();
809 if (rsig
->vector_width() > rwidth
)
810 rwidth
= rsig
->vector_width();
815 NetModulo
*mod
= new NetModulo(scope
, scope
->local_symbol(), rwidth
,
816 lsig
->vector_width(),
817 rsig
->vector_width());
818 mod
->set_line(*this);
821 connect(mod
->pin_DataA(), lsig
->pin(0));
822 connect(mod
->pin_DataB(), rsig
->pin(0));
824 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
825 NetNet::IMPLICIT
, rwidth
);
826 osig
->set_line(*this);
827 osig
->data_type(data_type
);
828 osig
->local_flag(true);
830 connect(mod
->pin_Result(), osig
->pin(0));
835 NetNet
* PEBinary::elaborate_net_log_(Design
*des
, NetScope
*scope
,
839 const NetExpr
* decay
) const
841 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
842 NetNet
*rsig
= right_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
844 cerr
<< get_line() << ": error: Cannot elaborate ";
850 cerr
<< get_line() << ": error: Cannot elaborate ";
859 gate
= new NetLogic(scope
, scope
->local_symbol(),
860 3, NetLogic::AND
, 1);
863 gate
= new NetLogic(scope
, scope
->local_symbol(),
869 gate
->rise_time(rise
);
870 gate
->fall_time(fall
);
871 gate
->decay_time(decay
);
873 // The first OR gate returns 1 if the left value is true...
874 if (lsig
->vector_width() > 1) {
875 NetUReduce
*gate_tmp
= new NetUReduce(scope
, scope
->local_symbol(),
877 lsig
->vector_width());
878 connect(gate_tmp
->pin(1), lsig
->pin(0));
879 connect(gate
->pin(1), gate_tmp
->pin(0));
881 /* The reduced logical value is a new nexus, create a
882 temporary signal to represent it. */
883 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
884 NetNet::IMPLICIT
, 1);
885 tmp
->data_type(IVL_VT_LOGIC
);
886 tmp
->local_flag(true);
887 connect(gate
->pin(1), tmp
->pin(0));
889 des
->add_node(gate_tmp
);
892 connect(gate
->pin(1), lsig
->pin(0));
895 // The second OR gate returns 1 if the right value is true...
896 if (rsig
->vector_width() > 1) {
897 NetUReduce
*gate_tmp
= new NetUReduce(scope
, scope
->local_symbol(),
899 rsig
->vector_width());
900 connect(gate_tmp
->pin(1), rsig
->pin(0));
901 connect(gate
->pin(2), gate_tmp
->pin(0));
903 /* The reduced logical value is a new nexus, create a
904 temporary signal to represent it. */
905 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
906 NetNet::IMPLICIT
, 1);
907 tmp
->data_type(IVL_VT_LOGIC
);
908 tmp
->local_flag(true);
909 connect(gate
->pin(2), tmp
->pin(0));
911 des
->add_node(gate_tmp
);
914 connect(gate
->pin(2), rsig
->pin(0));
917 // The output is the AND/OR of the two logic values.
918 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
);
919 osig
->local_flag(true);
920 osig
->data_type(IVL_VT_LOGIC
);
921 connect(gate
->pin(0), osig
->pin(0));
926 NetNet
* PEBinary::elaborate_net_mul_(Design
*des
, NetScope
*scope
,
930 const NetExpr
* decay
) const
932 verinum
*lnum
= left_
->eval_const(des
, scope
);
933 verinum
*rnum
= right_
->eval_const(des
, scope
);
935 /* Detect and handle the special case that both the operands
936 of the multiply are constant expressions. Evaluate the
937 value and make this a simple constant. */
939 verinum prod
= *lnum
* *rnum
;
943 verinum
res (verinum::V0
, lwidth
);
944 for (unsigned idx
= 0
945 ; idx
< prod
.len() && idx
< lwidth
947 res
.set(idx
, prod
.get(idx
));
950 NetConst
*odev
= new NetConst(scope
, scope
->local_symbol(), res
);
952 odev
->set_line(*this);
954 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
955 NetNet::IMPLICIT
, lwidth
);
956 osig
->set_line(*this);
957 osig
->local_flag(true);
958 osig
->data_type(IVL_VT_LOGIC
);
960 connect(odev
->pin(0), osig
->pin(0));
965 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
966 if (lsig
== 0) return 0;
967 NetNet
*rsig
= right_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
968 if (rsig
== 0) return 0;
970 // The mult is signed if both its operands are signed.
971 bool arith_is_signed
= lsig
->get_signed() && rsig
->get_signed();
973 /* The arguments of a divide must have the same type. */
974 if (lsig
->data_type() != rsig
->data_type()) {
975 cerr
<< get_line() << ": error: Arguments of multiply "
976 << "have different data types." << endl
;
977 cerr
<< get_line() << ": : Left argument is "
978 << lsig
->data_type() << ", right argument is "
979 << rsig
->data_type() << "." << endl
;
983 ivl_variable_type_t data_type
= lsig
->data_type();
985 unsigned rwidth
= lwidth
;
987 rwidth
= lsig
->vector_width() + rsig
->vector_width();
991 if (arith_is_signed
) {
992 lsig
= pad_to_width_signed(des
, lsig
, rwidth
);
993 rsig
= pad_to_width_signed(des
, rsig
, rwidth
);
996 NetMult
*mult
= new NetMult(scope
, scope
->local_symbol(), rwidth
,
997 lsig
->vector_width(),
998 rsig
->vector_width());
999 mult
->set_line(*this);
1000 des
->add_node(mult
);
1002 mult
->set_signed( arith_is_signed
);
1004 connect(mult
->pin_DataA(), lsig
->pin(0));
1005 connect(mult
->pin_DataB(), rsig
->pin(0));
1007 // Make a signal to carry the output from the multiply.
1008 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1009 NetNet::IMPLICIT
, rwidth
);
1010 osig
->data_type(data_type
);
1011 osig
->local_flag(true);
1012 connect(mult
->pin_Result(), osig
->pin(0));
1017 NetNet
* PEBinary::elaborate_net_shift_(Design
*des
, NetScope
*scope
,
1019 const NetExpr
* rise
,
1020 const NetExpr
* fall
,
1021 const NetExpr
* decay
) const
1023 NetNet
*lsig
= left_
->elaborate_net(des
, scope
, lwidth
, 0, 0, 0);
1024 if (lsig
== 0) return 0;
1026 if (lsig
->vector_width() > lwidth
)
1027 lwidth
= lsig
->vector_width();
1029 bool right_flag
= op_
== 'r' || op_
== 'R';
1030 bool signed_flag
= op_
== 'R';
1031 ivl_variable_type_t data_type
= lsig
->data_type();
1033 /* Handle the special case of a constant shift amount. There
1034 is no reason in this case to create a gate at all, just
1035 connect the lsig to the osig with the bit positions
1036 shifted. Use a NetPartSelect to select the parts of the
1037 left expression that survive the shift, and a NetConcat to
1038 concatenate a constant for padding. */
1039 if (verinum
*rval
= right_
->eval_const(des
, scope
)) {
1040 assert(rval
->is_defined());
1041 unsigned dist
= rval
->as_ulong();
1043 /* Very special case: constant 0 shift. Simply return
1044 the left signal again. */
1045 if (dist
== 0) return lsig
;
1047 /* Another very special case: constant shift the entire
1048 value away. The result is a const. */
1049 if (dist
> lwidth
) {
1053 /* The construction that I'm making will ultimately
1054 connect its output to the osig here. This will be the
1055 result that I return from this function. */
1056 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1057 NetNet::WIRE
, lwidth
);
1058 osig
->data_type( data_type
);
1059 osig
->local_flag(true);
1062 /* Make the constant zero's that I'm going to pad to the
1063 top or bottom of the left expression. Attach a signal
1064 to its output so that I don't have to worry about it
1065 later. If the left expression is less then the
1066 desired width (and we are doing right shifts) then we
1067 can combine the expression padding with the distance
1068 padding to reduce nodes. */
1069 unsigned pad_width
= dist
;
1070 unsigned part_width
= lwidth
- dist
;
1071 if (op_
== 'r' || op_
== 'R') {
1072 if (lsig
->vector_width() < lwidth
) {
1073 pad_width
+= lwidth
- lsig
->vector_width();
1074 part_width
-= lwidth
- lsig
->vector_width();
1078 /* The left net must be the same width as the
1079 result. The part select that I'm about to make relies
1081 lsig
= pad_to_width(des
, lsig
, lwidth
);
1085 NetNet
*zero
= new NetNet(scope
, scope
->local_symbol(),
1086 NetNet::WIRE
, pad_width
);
1087 zero
->data_type( data_type
);
1088 zero
->local_flag(true);
1089 zero
->set_line(*this);
1092 NetPartSelect
*sign_bit
1093 = new NetPartSelect(lsig
, lsig
->vector_width()-1,
1094 1, NetPartSelect::VP
);
1095 des
->add_node(sign_bit
);
1096 NetReplicate
*sign_pad
1097 = new NetReplicate(scope
, scope
->local_symbol(),
1098 pad_width
, pad_width
);
1099 des
->add_node(sign_pad
);
1100 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1102 tmp
->data_type( data_type
);
1103 tmp
->local_flag(true);
1104 tmp
->set_line(*this);
1105 connect(sign_bit
->pin(0), tmp
->pin(0));
1106 connect(sign_bit
->pin(0), sign_pad
->pin(1));
1108 connect(zero
->pin(0), sign_pad
->pin(0));
1111 NetConst
*zero_c
= new NetConst(scope
, scope
->local_symbol(),
1112 verinum(verinum::V0
, pad_width
));
1113 des
->add_node(zero_c
);
1114 connect(zero
->pin(0), zero_c
->pin(0));
1117 /* Make a concatenation operator that will join the
1118 part-selected right expression at the pad values. */
1119 NetConcat
*cc
= new NetConcat(scope
, scope
->local_symbol(),
1121 cc
->set_line(*this);
1123 connect(cc
->pin(0), osig
->pin(0));
1125 /* Make the part select of the left expression and
1126 connect it to the lsb or msb of the concatenation,
1127 depending on the direction of the shift. */
1131 case 'l': // Left shift === {lsig, zero}
1132 part
= new NetPartSelect(lsig
, 0, part_width
,
1134 connect(cc
->pin(1), zero
->pin(0));
1135 connect(cc
->pin(2), part
->pin(0));
1138 case 'r': // right-shift === {zero, lsig}
1139 part
= new NetPartSelect(lsig
, dist
, part_width
,
1141 connect(cc
->pin(1), part
->pin(0));
1142 connect(cc
->pin(2), zero
->pin(0));
1148 des
->add_node(part
);
1150 if (debug_elaborate
) {
1151 cerr
<< get_line() << ": debug: Elaborate shift "
1152 << "(" << op_
<< ") as concatenation of "
1153 << pad_width
<< " zeros with " << part_width
1154 << " bits of expression." << endl
;
1157 /* Attach a signal to the part select output (NetConcat
1159 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1160 NetNet::WIRE
, part_width
);
1161 tmp
->data_type( data_type
);
1162 tmp
->local_flag(true);
1163 tmp
->set_line(*this);
1164 connect(part
->pin(0), tmp
->pin(0));
1169 // Calculate the number of useful bits for the shift amount,
1170 // and elaborate the right_ expression as the shift amount.
1172 while ((1U << dwid
) < lwidth
)
1175 NetNet
*rsig
= right_
->elaborate_net(des
, scope
, dwid
, 0, 0, 0);
1176 if (rsig
== 0) return 0;
1178 // Make the shift device itself, and the output
1179 // NetNet. Connect the Result output pins to the osig signal
1180 NetCLShift
*gate
= new NetCLShift(scope
, scope
->local_symbol(),
1181 lwidth
, rsig
->vector_width(),
1182 right_flag
, signed_flag
);
1183 des
->add_node(gate
);
1185 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1186 NetNet::WIRE
, lwidth
);
1187 osig
->data_type( data_type
);
1188 osig
->local_flag(true);
1189 osig
->set_signed(signed_flag
);
1191 connect(osig
->pin(0), gate
->pin_Result());
1193 // Connect the lsig (the left expression) to the Data input,
1194 // and pad it if necessary. The lwidth is the width of the
1195 // NetCLShift gate, and the D input must match.
1196 if (lsig
->vector_width() < lwidth
)
1197 lsig
= pad_to_width(des
, lsig
, lwidth
);
1199 assert(lsig
->vector_width() <= lwidth
);
1200 connect(lsig
->pin(0), gate
->pin_Data());
1202 // Connect the rsig (the shift amount expression) to the
1204 connect(rsig
->pin(0), gate
->pin_Distance());
1206 if (debug_elaborate
) {
1207 cerr
<< get_line() << ": debug: "
1208 << "Elaborate LPM_SHIFT: width="<<gate
->width()
1209 << ", swidth="<< gate
->width_dist() << endl
;
1216 * This method elaborates a call to a function in the context of a
1217 * continuous assignment. The definition of the function contains a
1218 * list of the ports, and an output port. The NetEUFunc that I create
1219 * here has a port for all the input ports and the output port. The
1220 * ports are connected by pins.
1222 NetNet
* PECallFunction::elaborate_net(Design
*des
, NetScope
*scope
,
1224 const NetExpr
* rise
,
1225 const NetExpr
* fall
,
1226 const NetExpr
* decay
,
1227 Link::strength_t drive0
,
1228 Link::strength_t drive1
) const
1230 unsigned errors
= 0;
1231 unsigned func_pins
= 0;
1233 if (path_
.front().name
[0] == '$')
1234 return elaborate_net_sfunc_(des
, scope
,
1235 width
, rise
, fall
, decay
,
1239 /* Look up the function definition. */
1240 NetFuncDef
*def
= des
->find_function(scope
, path_
);
1242 cerr
<< get_line() << ": error: No function " << path_
<<
1243 " in this context (" << scope_path(scope
) << ")." << endl
;
1249 NetScope
*dscope
= def
->scope();
1252 /* This must be a ufuction that returns a signal. */
1253 assert(def
->return_sig());
1255 /* check the validity of the parameters. */
1256 if (! check_call_matches_definition_(des
, dscope
))
1259 /* Elaborate all the parameters of the function call,
1260 and collect the resulting NetNet objects. All the
1261 parameters take on the size of the target port. */
1263 svector
<NetNet
*> eparms (def
->port_count());
1264 for (unsigned idx
= 0 ; idx
< eparms
.count() ; idx
+= 1) {
1265 const NetNet
* port_reg
= def
->port(idx
);
1266 NetNet
*tmp
= parms_
[idx
]->elaborate_net(des
, scope
,
1267 port_reg
->vector_width(),
1272 cerr
<< get_line() << ": error: Unable to elaborate "
1273 << "port " << idx
<< " of call to " << path_
<<
1279 func_pins
+= tmp
->pin_count();
1287 NetUserFunc
*net
= new NetUserFunc(scope
,
1288 scope
->local_symbol(),
1292 /* Create an output signal and connect it to the output pins
1293 of the function net. */
1294 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1296 def
->return_sig()->vector_width());
1297 osig
->local_flag(true);
1298 osig
->data_type(def
->return_sig()->data_type());
1300 connect(net
->pin(0), osig
->pin(0));
1302 /* Connect the parameter pins to the parameter expressions. */
1303 for (unsigned idx
= 0 ; idx
< eparms
.count() ; idx
+= 1) {
1304 const NetNet
* port
= def
->port(idx
);
1305 NetNet
*cur
= eparms
[idx
];
1307 NetNet
*tmp
= pad_to_width(des
, cur
, port
->vector_width());
1309 connect(net
->pin(idx
+1), tmp
->pin(0));
1315 NetNet
* PECallFunction::elaborate_net_sfunc_(Design
*des
, NetScope
*scope
,
1317 const NetExpr
* rise
,
1318 const NetExpr
* fall
,
1319 const NetExpr
* decay
,
1320 Link::strength_t drive0
,
1321 Link::strength_t drive1
) const
1323 perm_string name
= peek_tail_name(path_
);
1325 /* Handle the special case that the function call is to
1326 $signed. This takes a single expression argument, and
1327 forces it to be a signed result. Otherwise, it is as if the
1328 $signed did not exist. */
1329 if (strcmp(name
, "$signed") == 0) {
1330 if ((parms_
.count() != 1) || (parms_
[0] == 0)) {
1331 cerr
<< get_line() << ": error: The $signed() function "
1332 << "takes exactly one(1) argument." << endl
;
1337 PExpr
*expr
= parms_
[0];
1338 NetNet
*sub
= expr
->elaborate_net(des
, scope
, width
, rise
,
1339 fall
, decay
, drive0
, drive1
);
1340 sub
->set_signed(true);
1344 /* handle $unsigned like $signed */
1345 if (strcmp(name
, "$unsigned") == 0) {
1346 if ((parms_
.count() != 1) || (parms_
[0] == 0)) {
1347 cerr
<< get_line() << ": error: The $unsigned() function "
1348 << "takes exactly one(1) argument." << endl
;
1353 PExpr
*expr
= parms_
[0];
1354 NetNet
*sub
= expr
->elaborate_net(des
, scope
, width
, rise
,
1355 fall
, decay
, drive0
, drive1
);
1356 sub
->set_signed(false);
1360 const struct sfunc_return_type
*def
= lookup_sys_func(name
);
1363 cerr
<< get_line() << ": error: System function "
1364 << peek_tail_name(path_
) << " not defined." << endl
;
1369 NetSysFunc
*net
= new NetSysFunc(scope
, scope
->local_symbol(),
1370 def
, 1+parms_
.count());
1372 net
->set_line(*this);
1374 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1375 NetNet::WIRE
, def
->wid
);
1376 osig
->local_flag(true);
1377 osig
->data_type(def
->type
);
1378 osig
->set_line(*this);
1380 connect(net
->pin(0), osig
->pin(0));
1382 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1) {
1383 NetNet
*tmp
= parms_
[idx
]->elaborate_net(des
, scope
, 0,
1385 Link::STRONG
, Link::STRONG
);
1387 cerr
<< get_line() << ": error: Unable to elaborate "
1388 << "port " << idx
<< " of call to " << path_
<<
1393 connect(net
->pin(1+idx
), tmp
->pin(0));
1400 * The concatenation operator, as a net, is a wide signal that is
1401 * connected to all the pins of the elaborated expression nets.
1403 NetNet
* PEConcat::elaborate_net(Design
*des
, NetScope
*scope
,
1405 const NetExpr
* rise
,
1406 const NetExpr
* fall
,
1407 const NetExpr
* decay
,
1408 Link::strength_t drive0
,
1409 Link::strength_t drive1
) const
1411 svector
<NetNet
*>nets (parms_
.count());
1412 unsigned vector_width
= 0;
1413 unsigned errors
= 0;
1414 unsigned repeat
= 1;
1416 /* The repeat expression must evaluate to a compile-time
1417 constant. This is used to generate the width of the
1420 NetExpr
*etmp
= elab_and_eval(des
, scope
, repeat_
, -1);
1422 NetEConst
*erep
= dynamic_cast<NetEConst
*>(etmp
);
1425 cerr
<< get_line() << ": error: Unable to "
1426 << "evaluate constant repeat expression." << endl
;
1431 repeat
= erep
->value().as_ulong();
1435 cerr
<< get_line() << ": error: Concatenation epeat "
1443 if (debug_elaborate
) {
1444 cerr
<< get_line() <<": debug: PEConcat concat repeat="
1445 << repeat
<< "." << endl
;
1448 /* The operands of the concatenation must contain all
1449 self-determined arguments. Set this flag to force an error
1450 message if this is not the case. */
1451 const bool save_flag
= must_be_self_determined_flag
;
1452 must_be_self_determined_flag
= true;
1454 /* Elaborate the operands of the concatenation. */
1455 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
1457 if (parms_
[idx
] == 0) {
1458 cerr
<< get_line() << ": error: Empty expressions "
1459 << "not allowed in concatenations." << endl
;
1464 /* Look for the special case of an unsized number in a
1465 concatenation expression. Mark this as an error, but
1466 allow elaboration to continue to see if I can find
1469 if (PENumber
*tmp
= dynamic_cast<PENumber
*>(parms_
[idx
])) {
1470 if (tmp
->value().has_len() == false) {
1471 cerr
<< get_line() << ": error: Number "
1472 << tmp
->value() << " with indefinite size"
1473 << " in concatenation." << endl
;
1478 nets
[idx
] = parms_
[idx
]->elaborate_net(des
, scope
, 0,
1483 vector_width
+= nets
[idx
]->vector_width();
1486 must_be_self_determined_flag
= save_flag
;
1488 /* If any of the sub expressions failed to elaborate, then
1489 delete all those that did and abort myself. */
1491 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
1492 if (nets
[idx
]) delete nets
[idx
];
1498 if (debug_elaborate
) {
1499 cerr
<< get_line() <<": debug: PEConcat concat collected "
1500 << "width=" << vector_width
<< ", repeat=" << repeat
1501 << " of " << nets
.count() << " expressions." << endl
;
1504 NetConcat
*dev
= new NetConcat(scope
, scope
->local_symbol(),
1505 vector_width
*repeat
,
1506 nets
.count()*repeat
);
1507 dev
->set_line(*this);
1510 /* Make the temporary signal that connects to all the
1511 operands, and connect it up. Scan the operands of the
1512 concat operator from least significant to most significant,
1513 which is opposite from how they are given in the list.
1515 Allow for a repeat count other than 1 by repeating the
1516 connect loop as many times as necessary. */
1518 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
1519 NetNet::IMPLICIT
, vector_width
* repeat
);
1520 osig
->data_type(IVL_VT_LOGIC
);
1522 connect(dev
->pin(0), osig
->pin(0));
1524 unsigned cur_pin
= 1;
1525 for (unsigned rpt
= 0; rpt
< repeat
; rpt
+= 1) {
1526 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
1527 NetNet
*cur
= nets
[nets
.count()-idx
-1];
1528 connect(dev
->pin(cur_pin
++), cur
->pin(0));
1533 osig
->local_flag(true);
1538 * This private method handles the special case that we have a
1539 * non-constant bit-select of an identifier. We already know that the
1540 * signal that is represented is "sig".
1542 NetNet
* PEIdent::elaborate_net_bitmux_(Design
*des
, NetScope
*scope
,
1544 const NetExpr
* rise
,
1545 const NetExpr
* fall
,
1546 const NetExpr
* decay
,
1547 Link::strength_t drive0
,
1548 Link::strength_t drive1
) const
1550 const name_component_t
&name_tail
= path_
.back();
1551 ivl_assert(*this, !name_tail
.index
.empty());
1553 const index_component_t
&index_tail
= name_tail
.index
.back();
1554 ivl_assert(*this, index_tail
.sel
== index_component_t::SEL_BIT
);
1555 ivl_assert(*this, index_tail
.msb
!= 0);
1556 ivl_assert(*this, index_tail
.lsb
== 0);
1558 /* Elaborate the selector. */
1561 if (sig
->msb() < sig
->lsb()) {
1562 NetExpr
*sel_expr
= index_tail
.msb
->elaborate_expr(des
, scope
, -1, false);
1563 sel_expr
= make_sub_expr(sig
->lsb(), sel_expr
);
1564 if (NetExpr
*tmp
= sel_expr
->eval_tree()) {
1569 sel
= sel_expr
->synthesize(des
);
1571 } else if (sig
->lsb() != 0) {
1572 NetExpr
*sel_expr
= index_tail
.msb
->elaborate_expr(des
, scope
, -1,false);
1573 sel_expr
= make_add_expr(sel_expr
, - sig
->lsb());
1574 if (NetExpr
*tmp
= sel_expr
->eval_tree()) {
1579 sel
= sel_expr
->synthesize(des
);
1582 sel
= index_tail
.msb
->elaborate_net(des
, scope
, 0, 0, 0, 0);
1585 if (debug_elaborate
) {
1586 cerr
<< get_line() << ": debug: Create NetPartSelect "
1587 << "using signal " << sel
->name() << " as selector"
1591 /* Create a part select that takes a non-constant offset and a
1593 NetPartSelect
*mux
= new NetPartSelect(sig
, sel
, 1);
1595 mux
->set_line(*this);
1597 NetNet
*out
= new NetNet(scope
, scope
->local_symbol(),
1599 out
->data_type(sig
->data_type());
1601 connect(out
->pin(0), mux
->pin(0));
1605 NetNet
* PEIdent::elaborate_net(Design
*des
, NetScope
*scope
,
1607 const NetExpr
* rise
,
1608 const NetExpr
* fall
,
1609 const NetExpr
* decay
,
1610 Link::strength_t drive0
,
1611 Link::strength_t drive1
) const
1613 ivl_assert(*this, scope
);
1615 const name_component_t
&name_tail
= path_
.back();
1618 const NetExpr
*par
= 0;
1621 symbol_search(des
, scope
, path_
, sig
, par
, eve
);
1623 /* If this is a parameter name, then create a constant node
1624 that connects to a signal with the correct name. */
1627 const NetEConst
*pc
= dynamic_cast<const NetEConst
*>(par
);
1629 verinum pvalue
= pc
->value();
1631 /* If the desired lwidth is more than the width of the
1632 constant value, extend the value to fit the desired
1634 if (lwidth
> pvalue
.len()) {
1635 verinum
tmp ((uint64_t)0, lwidth
);
1636 for (unsigned idx
= 0 ; idx
< pvalue
.len() ; idx
+= 1)
1637 tmp
.set(idx
, pvalue
.get(idx
));
1642 sig
= new NetNet(scope
, scope
->local_symbol(),
1643 NetNet::IMPLICIT
, pvalue
.len());
1644 sig
->set_line(*this);
1645 sig
->data_type(IVL_VT_LOGIC
);
1646 NetConst
*cp
= new NetConst(scope
, scope
->local_symbol(),
1648 cp
->set_line(*this);
1650 for (unsigned idx
= 0; idx
< sig
->pin_count(); idx
+= 1)
1651 connect(sig
->pin(idx
), cp
->pin(idx
));
1654 /* Check for the error case that the name is not found, and it
1655 is hierarchical. We can't just create a name in another
1656 scope, it's just not allowed. */
1657 if (sig
== 0 && path_
.size() != 1) {
1658 cerr
<< get_line() << ": error: The hierarchical name "
1659 << path_
<< " is undefined in "
1660 << scope_path(scope
) << "." << endl
;
1662 pform_name_t tmp_path
= path_
;
1663 tmp_path
.pop_back();
1665 list
<hname_t
> stmp_path
= eval_scope_path(des
, scope
, tmp_path
);
1666 NetScope
*tmp_scope
= des
->find_scope(scope
, stmp_path
);
1667 if (tmp_scope
== 0) {
1668 cerr
<< get_line() << ": : I can't even find "
1669 << "the scope " << tmp_path
<< "." << endl
;
1676 /* Fallback, this may be an implicitly declared net. */
1678 NetNet::Type nettype
= scope
->default_nettype();
1679 sig
= new NetNet(scope
, name_tail
.name
,
1681 sig
->data_type(IVL_VT_LOGIC
);
1683 if (error_implicit
|| (nettype
== NetNet::NONE
)) {
1684 cerr
<< get_line() << ": error: "
1685 << scope_path(scope
) << "." << name_tail
.name
1686 << " not defined in this scope." << endl
;
1689 } else if (warn_implicit
) {
1690 cerr
<< get_line() << ": warning: implicit "
1691 "definition of wire " << scope_path(scope
)
1692 << "." << name_tail
.name
<< "." << endl
;
1696 ivl_assert(*this, sig
);
1698 /* Handle the case that this is an array elsewhere. */
1699 if (sig
->array_dimensions() > 0) {
1700 if (name_tail
.index
.size() == 0) {
1701 cerr
<< get_line() << ": error: Array " << sig
->name()
1702 << " cannot be used here without an index." << endl
;
1707 return elaborate_net_array_(des
, scope
, sig
, lwidth
,
1712 return elaborate_net_net_(des
, scope
, sig
, lwidth
,
1713 rise
, fall
, decay
, drive0
, drive1
);
1717 NetNet
* PEIdent::process_select_(Design
*des
, NetScope
*scope
,
1721 // If there are more index items then there are array
1722 // dimensions, then treat them as word part selects. For
1723 // example, if this is a memory array, then array dimensions
1724 // is the first and part select the remainder.
1725 unsigned midx
, lidx
;
1726 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
1729 unsigned part_count
= midx
-lidx
+1;
1731 // Maybe this is a full-width constant part select? If
1733 if (part_count
== sig
->vector_width())
1736 if (debug_elaborate
) {
1737 cerr
<< get_line() << ": debug: Elaborate part select"
1738 << " of word from " << sig
->name() << "[base="<<lidx
1739 << " wid=" << part_count
<< "]" << endl
;
1742 NetPartSelect
*ps
= new NetPartSelect(sig
, lidx
, part_count
,
1747 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1748 NetNet::WIRE
, part_count
-1, 0);
1749 tmp
->data_type( sig
->data_type() );
1750 tmp
->local_flag(true);
1751 connect(tmp
->pin(0), ps
->pin(0));
1756 NetNet
* PEIdent::elaborate_net_net_(Design
*des
, NetScope
*scope
,
1757 NetNet
*sig
, unsigned lwidth
,
1758 const NetExpr
* rise
,
1759 const NetExpr
* fall
,
1760 const NetExpr
* decay
,
1761 Link::strength_t drive0
,
1762 Link::strength_t drive1
) const
1764 const name_component_t
&name_tail
= path_
.back();
1766 index_component_t::ctype_t use_sel
= index_component_t::SEL_NONE
;
1767 if (!name_tail
.index
.empty())
1768 use_sel
= name_tail
.index
.back().sel
;
1771 case index_component_t::SEL_IDX_UP
:
1772 case index_component_t::SEL_IDX_DO
:
1773 return elaborate_net_net_idx_up_(des
, scope
, sig
, lwidth
,
1774 rise
, fall
, decay
, drive0
, drive1
);
1780 /* Catch the case of a non-constant bit select. That should be
1781 handled elsewhere. */
1782 if (use_sel
== index_component_t::SEL_BIT
) {
1783 const index_component_t
&index_tail
= name_tail
.index
.back();
1785 verinum
*mval
= index_tail
.msb
->eval_const(des
, scope
);
1787 return elaborate_net_bitmux_(des
, scope
, sig
, rise
,
1788 fall
, decay
, drive0
, drive1
);
1794 unsigned midx
, lidx
;
1795 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
1798 unsigned part_count
= midx
-lidx
+1;
1800 if (part_count
!= sig
->vector_width()) {
1801 if (debug_elaborate
) {
1802 cerr
<< get_line() << ": debug: Elaborate part select "
1803 << sig
->name() << "[base="<<lidx
1804 << " wid=" << part_count
<< "]" << endl
;
1807 NetPartSelect
*ps
= new NetPartSelect(sig
, lidx
, part_count
,
1812 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1813 NetNet::WIRE
, part_count
-1, 0);
1814 tmp
->data_type( sig
->data_type() );
1815 tmp
->local_flag(true);
1816 connect(tmp
->pin(0), ps
->pin(0));
1826 NetNet
* PEIdent::elaborate_net_net_idx_up_(Design
*des
, NetScope
*scope
,
1827 NetNet
*sig
, unsigned lwidth
,
1828 const NetExpr
* rise
,
1829 const NetExpr
* fall
,
1830 const NetExpr
* decay
,
1831 Link::strength_t drive0
,
1832 Link::strength_t drive1
) const
1834 const name_component_t
&name_tail
= path_
.back();
1835 ivl_assert(*this, !name_tail
.index
.empty());
1837 const index_component_t
&index_tail
= name_tail
.index
.back();
1838 ivl_assert(*this, index_tail
.lsb
!= 0);
1839 ivl_assert(*this, index_tail
.msb
!= 0);
1841 NetExpr
*base
= elab_and_eval(des
, scope
, index_tail
.msb
, -1);
1843 unsigned long wid
= 0;
1844 calculate_up_do_width_(des
, scope
, wid
);
1846 bool down_flag
= name_tail
.index
.back().sel
==index_component_t::SEL_IDX_DO
;
1848 // Handle the special case that the base is constant as
1849 // well. In this case it can be converted to a conventional
1851 if (NetEConst
*base_c
= dynamic_cast<NetEConst
*> (base
)) {
1852 long lsv
= base_c
->value().as_long();
1854 // convert from -: to +: form.
1855 if (down_flag
) lsv
-= (wid
-1);
1857 // If the part select convers exactly the entire
1858 // vector, then do not bother with it. Return the
1860 if (sig
->sb_to_idx(lsv
) == 0 && wid
== sig
->vector_width())
1863 NetPartSelect
*sel
= new NetPartSelect(sig
, sig
->sb_to_idx(lsv
),
1864 wid
, NetPartSelect::VP
);
1865 sel
->set_line(*this);
1868 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1870 tmp
->set_line(*this);
1871 tmp
->data_type(sig
->data_type());
1872 connect(tmp
->pin(0), sel
->pin(0));
1878 if (sig
->msb() > sig
->lsb()) {
1879 long offset
= sig
->lsb();
1883 base
= make_add_expr(base
, 0-offset
);
1885 long vwid
= sig
->lsb() - sig
->msb() + 1;
1886 long offset
= sig
->msb();
1889 base
= make_sub_expr(vwid
-offset
-wid
, base
);
1892 NetPartSelect
*sel
= new NetPartSelect(sig
, base
->synthesize(des
), wid
);
1893 sel
->set_line(*this);
1896 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1898 tmp
->set_line(*this);
1899 tmp
->data_type(sig
->data_type());
1900 connect(tmp
->pin(0), sel
->pin(0));
1906 NetNet
* PEIdent::elaborate_net_array_(Design
*des
, NetScope
*scope
,
1907 NetNet
*sig
, unsigned lwidth
,
1908 const NetExpr
* rise
,
1909 const NetExpr
* fall
,
1910 const NetExpr
* decay
,
1911 Link::strength_t drive0
,
1912 Link::strength_t drive1
) const
1914 const name_component_t
&name_tail
= path_
.back();
1915 ivl_assert(*this, name_tail
.index
.size() >= 1);
1916 const index_component_t
&index_head
= name_tail
.index
.front();
1917 ivl_assert(*this, index_head
.sel
== index_component_t::SEL_BIT
);
1918 ivl_assert(*this, index_head
.msb
!= 0);
1919 ivl_assert(*this, index_head
.lsb
== 0);
1921 if (debug_elaborate
)
1922 cerr
<< get_line() << ": debug: elaborate array "
1923 << name_tail
.name
<< " with index " << index_head
<< endl
;
1925 NetExpr
*index_ex
= elab_and_eval(des
, scope
, index_head
.msb
, -1);
1929 if (NetEConst
*index_co
= dynamic_cast<NetEConst
*> (index_ex
)) {
1930 long index
= index_co
->value().as_long();
1932 if (!sig
->array_index_is_valid(index
)) {
1933 // Oops! The index is a constant known to be
1934 // outside the array. Change the expression to a
1935 // constant X vector.
1936 verinum
xxx (verinum::Vx
, sig
->vector_width());
1937 NetConst
*con_n
= new NetConst(scope
, scope
->local_symbol(), xxx
);
1938 des
->add_node(con_n
);
1939 con_n
->set_line(*index_co
);
1941 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1942 NetNet::IMPLICIT
, sig
->vector_width());
1943 tmp
->set_line(*this);
1944 tmp
->local_flag(true);
1945 tmp
->data_type(sig
->data_type());
1946 connect(tmp
->pin(0), con_n
->pin(0));
1950 assert(sig
->array_index_is_valid(index
));
1951 index
= sig
->array_index_to_address(index
);
1953 if (debug_elaborate
) {
1954 cerr
<< get_line() << ": debug: Elaborate word "
1955 << index
<< " of " << sig
->name() << endl
;
1958 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1959 NetNet::IMPLICIT
, sig
->vector_width());
1960 tmp
->set_line(*this);
1961 tmp
->local_flag(true);
1962 tmp
->data_type(sig
->data_type());
1963 connect(tmp
->pin(0), sig
->pin(index
));
1965 // If there are more indices then needed to get to the
1966 // word, then there is a part/bit select for the word.
1967 if (name_tail
.index
.size() > sig
->array_dimensions())
1968 tmp
= process_select_(des
, scope
, tmp
);
1973 unsigned selwid
= index_ex
->expr_width();
1975 NetArrayDq
*mux
= new NetArrayDq(scope
, scope
->local_symbol(),
1977 mux
->set_line(*this);
1980 // Adjust the expression to calculate the canonical offset?
1981 if (long array_base
= sig
->array_first()) {
1982 index_ex
= make_add_expr(index_ex
, 0-array_base
);
1985 NetNet
*index_net
= index_ex
->synthesize(des
);
1986 connect(mux
->pin_Address(), index_net
->pin(0));
1988 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1989 NetNet::IMPLICIT
, sig
->vector_width());
1990 tmp
->set_line(*this);
1991 tmp
->local_flag(true);
1992 tmp
->data_type(sig
->data_type());
1993 connect(tmp
->pin(0), mux
->pin_Result());
1996 // If there are more index items then there are array
1997 // dimensions, then treat them as word part selects. For
1998 // example, if this is a memory array, then array dimensions
2000 unsigned midx
, lidx
;
2001 if (eval_part_select_(des
, scope
, sig
, midx
, lidx
)) do {
2003 unsigned part_count
= midx
-lidx
+1;
2005 // Maybe this is a full-width constant part select? If
2007 if (part_count
== sig
->vector_width())
2010 if (debug_elaborate
) {
2011 cerr
<< get_line() << ": debug: Elaborate part select"
2012 << " of word from " << sig
->name() << "[base="<<lidx
2013 << " wid=" << part_count
<< "]" << endl
;
2016 NetPartSelect
*ps
= new NetPartSelect(sig
, lidx
, part_count
,
2021 NetNet
*tmp2
= new NetNet(scope
, scope
->local_symbol(),
2022 NetNet::WIRE
, part_count
-1, 0);
2023 tmp2
->data_type( tmp
->data_type() );
2024 tmp2
->local_flag(true);
2025 connect(tmp2
->pin(0), ps
->pin(0));
2030 if (name_tail
.index
.size() > sig
->array_dimensions())
2031 tmp
= process_select_(des
, scope
, sig
);
2038 * The concatenation is also OK an an l-value. This method elaborates
2039 * it as a structural l-value. The return values is the *input* net of
2040 * the l-value, which may feed via part selects to the final
2041 * destination. The caller can connect gate outputs to this signal to
2042 * make the l-value connections.
2044 NetNet
* PEConcat::elaborate_lnet_common_(Design
*des
, NetScope
*scope
,
2045 bool implicit_net_ok
,
2046 bool bidirectional_flag
) const
2050 svector
<NetNet
*>nets (parms_
.count());
2052 unsigned errors
= 0;
2055 cerr
<< get_line() << ": sorry: I do not know how to"
2056 " elaborate repeat concatenation nets." << endl
;
2060 /* Elaborate the operands of the concatenation. */
2061 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
2063 if (debug_elaborate
) {
2064 cerr
<< get_line() << ": debug: Elaborate subexpression "
2065 << idx
<< " of " << nets
.count() << " l-values: "
2066 << *parms_
[idx
] << endl
;
2069 if (parms_
[idx
] == 0) {
2070 cerr
<< get_line() << ": error: Empty expressions "
2071 << "not allowed in concatenations." << endl
;
2076 if (bidirectional_flag
) {
2077 nets
[idx
] = parms_
[idx
]->elaborate_bi_net(des
, scope
);
2079 nets
[idx
] = parms_
[idx
]->elaborate_lnet(des
, scope
,
2085 width
+= nets
[idx
]->vector_width();
2088 /* If any of the sub expressions failed to elaborate, then
2089 delete all those that did and abort myself. */
2091 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
2092 if (nets
[idx
]) delete nets
[idx
];
2098 /* Make the temporary signal that connects to all the
2099 operands, and connect it up. Scan the operands of the
2100 concat operator from most significant to least significant,
2101 which is the order they are given in the concat list. */
2103 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
2104 NetNet::IMPLICIT
, width
);
2106 /* Assume that the data types of the nets are all the same, so
2107 we can take the data type of any, the first will do. */
2108 osig
->data_type(nets
[0]->data_type());
2109 osig
->local_flag(true);
2110 osig
->set_line(*this);
2112 if (debug_elaborate
) {
2113 cerr
<< get_line() << ": debug: Generating part selects "
2114 << "to connect input l-value to subexpressions."
2118 NetPartSelect::dir_t part_dir
= bidirectional_flag
2120 : NetPartSelect::VP
;
2122 for (unsigned idx
= 0 ; idx
< nets
.count() ; idx
+= 1) {
2123 unsigned wid
= nets
[idx
]->vector_width();
2124 unsigned off
= width
- wid
;
2125 NetPartSelect
*ps
= new NetPartSelect(osig
, off
, wid
, part_dir
);
2128 connect(ps
->pin(1), osig
->pin(0));
2129 connect(ps
->pin(0), nets
[idx
]->pin(0));
2131 assert(wid
<= width
);
2136 osig
->data_type(nets
[0]->data_type());
2137 osig
->local_flag(true);
2141 NetNet
* PEConcat::elaborate_lnet(Design
*des
, NetScope
*scope
,
2142 bool implicit_net_ok
) const
2144 return elaborate_lnet_common_(des
, scope
, implicit_net_ok
, false);
2147 NetNet
* PEConcat::elaborate_bi_net(Design
*des
, NetScope
*scope
) const
2149 return elaborate_lnet_common_(des
, scope
, true, true);
2153 * Elaborate a number as a NetConst object.
2155 NetNet
* PEFNumber::elaborate_net(Design
*des
, NetScope
*scope
,
2157 const NetExpr
* rise
,
2158 const NetExpr
* fall
,
2159 const NetExpr
* decay
,
2160 Link::strength_t drive0
,
2161 Link::strength_t drive1
) const
2163 if (debug_elaborate
) {
2164 cerr
<< get_line() << ": debug: Elaborate real literal node, "
2165 << "value=" << value() << "." << endl
;
2168 NetLiteral
*obj
= new NetLiteral(scope
, scope
->local_symbol(), value());
2169 obj
->set_line(*this);
2172 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
, 1);
2173 net
->data_type(IVL_VT_REAL
);
2174 net
->local_flag(true);
2176 connect(net
->pin(0), obj
->pin(0));
2181 * A private method to create an implicit net.
2183 NetNet
* PEIdent::make_implicit_net_(Design
*des
, NetScope
*scope
) const
2185 NetNet::Type nettype
= scope
->default_nettype();
2188 if (!error_implicit
&& nettype
!=NetNet::NONE
) {
2189 sig
= new NetNet(scope
, peek_tail_name(path_
),
2190 NetNet::IMPLICIT
, 1);
2191 /* Implicit nets are always scalar logic. */
2192 sig
->data_type(IVL_VT_LOGIC
);
2194 if (warn_implicit
) {
2195 cerr
<< get_line() << ": warning: implicit "
2196 "definition of wire logic " << scope_path(scope
)
2197 << "." << peek_tail_name(path_
) << "." << endl
;
2201 cerr
<< get_line() << ": error: Net " << path_
2202 << " is not defined in this context." << endl
;
2211 * This private method evaluates the part selects (if any) for the
2212 * signal. The sig argument is the NetNet already located for the
2213 * PEIdent name. The midx and lidx arguments are loaded with the
2214 * results, which may be the whole vector, or a single bit, or
2215 * anything in between. The values are in canonical indices.
2217 bool PEIdent::eval_part_select_(Design
*des
, NetScope
*scope
, NetNet
*sig
,
2218 unsigned&midx
, unsigned&lidx
) const
2220 const name_component_t
&name_tail
= path_
.back();
2221 // Only treat as part/bit selects any index that is beyond the
2222 // word selects for an array. This is not an array, then
2223 // dimensions==0 and any index is treated as a select.
2224 if (name_tail
.index
.size() <= sig
->array_dimensions()) {
2225 midx
= sig
->vector_width()-1;
2230 ivl_assert(*this, !name_tail
.index
.empty());
2232 const index_component_t
&index_tail
= name_tail
.index
.back();
2234 switch (index_tail
.sel
) {
2236 cerr
<< get_line() << ": internal error: "
2237 << "Unexpected sel_ value = " << index_tail
.sel
<< endl
;
2238 ivl_assert(*this, 0);
2241 case index_component_t::SEL_IDX_DO
:
2242 case index_component_t::SEL_IDX_UP
: {
2243 NetExpr
*tmp_ex
= elab_and_eval(des
, scope
, index_tail
.msb
, -1);
2244 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2245 ivl_assert(*this, tmp
);
2247 long midx_val
= tmp
->value().as_long();
2248 midx
= sig
->sb_to_idx(midx_val
);
2251 /* The width (a constant) is calculated here. */
2252 unsigned long wid
= 0;
2253 bool flag
= calculate_up_do_width_(des
, scope
, wid
);
2257 if (index_tail
.sel
== index_component_t::SEL_IDX_UP
)
2258 lidx
= sig
->sb_to_idx(midx_val
+wid
-1);
2260 lidx
= sig
->sb_to_idx(midx_val
-wid
+1);
2271 case index_component_t::SEL_PART
: {
2274 bool flag
= calculate_parts_(des
, scope
, msb
, lsb
);
2276 NetExpr
*tmp_ex
= elab_and_eval(des
, scope
, index_tail
.msb
, -1);
2277 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2280 long midx_val
= tmp
->value().as_long();
2281 midx
= sig
->sb_to_idx(midx_val
);
2284 tmp_ex
= elab_and_eval(des
, scope
, index_tail
.lsb
, -1);
2285 tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2287 cerr
<< get_line() << ": internal error: "
2288 << "lsb expression is not constant?: "
2289 << *tmp_ex
<< ", " << *index_tail
.lsb
<< endl
;
2293 long lidx_val
= tmp
->value().as_long();
2294 lidx
= sig
->sb_to_idx(lidx_val
);
2297 lidx
= sig
->sb_to_idx(lsb
);
2298 midx
= sig
->sb_to_idx(msb
);
2299 /* Detect reversed indices of a part select. */
2301 cerr
<< get_line() << ": error: Part select "
2302 << sig
->name() << "[" << msb
<< ":"
2303 << lsb
<< "] indices reversed." << endl
;
2304 cerr
<< get_line() << ": : Did you mean "
2305 << sig
->name() << "[" << lsb
<< ":"
2306 << msb
<< "]?" << endl
;
2307 unsigned tmp
= midx
;
2313 /* Detect a part select out of range. */
2314 if (midx
>= sig
->vector_width()) {
2315 cerr
<< get_line() << ": error: Part select "
2316 << sig
->name() << "[" << msb
<< ":"
2317 << lsb
<< "] out of range." << endl
;
2318 midx
= sig
->vector_width() - 1;
2325 case index_component_t::SEL_BIT
:
2326 if (name_tail
.index
.size() > sig
->array_dimensions()) {
2327 verinum
*mval
= index_tail
.msb
->eval_const(des
, scope
);
2329 cerr
<< get_line() << ": error: Index of " << path_
<<
2330 " needs to be constant in this context." <<
2332 cerr
<< get_line() << ": : Index expression is: "
2333 << *index_tail
.msb
<< endl
;
2334 cerr
<< get_line() << ": : Context scope is: "
2335 << scope_path(scope
) << endl
;
2341 midx
= sig
->sb_to_idx(mval
->as_long());
2342 if (midx
>= sig
->vector_width()) {
2343 cerr
<< get_line() << ": error: Index " << sig
->name()
2344 << "[" << mval
->as_long() << "] out of range."
2352 cerr
<< get_line() << ": internal error: "
2353 << "Bit select " << path_
<< endl
;
2354 ivl_assert(*this, 0);
2355 midx
= sig
->vector_width() - 1;
2365 * This is the common code for l-value nets and bi-directional
2366 * nets. There is very little that is different between the two cases,
2367 * so most of the work for both is done here.
2369 NetNet
* PEIdent::elaborate_lnet_common_(Design
*des
, NetScope
*scope
,
2370 bool implicit_net_ok
,
2371 bool bidirectional_flag
) const
2376 const NetExpr
*par
= 0;
2379 symbol_search(des
, scope
, path_
, sig
, par
, eve
);
2382 cerr
<< get_line() << ": error: named events (" << path_
2383 << ") cannot be l-values in continuous "
2384 << "assignments." << endl
;
2391 if (implicit_net_ok
) {
2393 sig
= make_implicit_net_(des
, scope
);
2398 cerr
<< get_line() << ": error: Net " << path_
2399 << " is not defined in this context." << endl
;
2407 /* Don't allow registers as assign l-values. */
2408 if (sig
->type() == NetNet::REG
) {
2409 cerr
<< get_line() << ": error: reg " << sig
->name()
2410 << "; cannot be driven by primitives"
2411 << " or continuous assignment." << endl
;
2416 if (sig
->port_type() == NetNet::PINPUT
) {
2417 cerr
<< get_line() << ": warning: L-value ``"
2418 << sig
->name() << "'' is also an input port." << endl
;
2419 cerr
<< sig
->get_line() << ": warning: input "
2420 << sig
->name() << "; is coerced to inout." << endl
;
2421 sig
->port_type(NetNet::PINOUT
);
2424 // Default part select is the entire word.
2425 unsigned midx
= sig
->vector_width()-1, lidx
= 0;
2426 // The default word select is the first.
2429 const name_component_t
&name_tail
= path_
.back();
2431 if (sig
->array_dimensions() > 0) {
2433 ivl_assert(*this, !name_tail
.index
.empty());
2435 const index_component_t
&index_head
= name_tail
.index
.front();
2436 ivl_assert(*this, index_head
.sel
== index_component_t::SEL_BIT
);
2438 NetExpr
*tmp_ex
= elab_and_eval(des
, scope
, index_head
.msb
, -1);
2439 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2442 long widx_val
= tmp
->value().as_long();
2443 widx
= sig
->array_index_to_address(widx_val
);
2446 if (debug_elaborate
)
2447 cerr
<< get_line() << ": debug: Use [" << widx
<< "]"
2448 << " to index l-value array." << endl
;
2450 } else if (!name_tail
.index
.empty()) {
2451 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
2455 unsigned subnet_wid
= midx
-lidx
+1;
2457 if (sig
->pin_count() > 1) {
2458 assert(widx
< sig
->pin_count());
2460 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2461 sig
->type(), sig
->vector_width());
2462 tmp
->set_line(*this);
2463 tmp
->local_flag(true);
2464 connect(sig
->pin(widx
), tmp
->pin(0));
2468 /* If the desired l-value vector is narrower then the
2469 signal itself, then use a NetPartSelect node to
2470 arrange for connection to the desired bits. All this
2471 can be skipped if the desired with matches the
2474 if (subnet_wid
!= sig
->vector_width()) {
2475 /* If we are processing a tran or inout, then the
2476 partselect is bi-directional. Otherwise, it is a
2477 Part-to-Vector select. */
2478 NetPartSelect::dir_t part_dir
;
2479 if (bidirectional_flag
)
2480 part_dir
= NetPartSelect::BI
;
2482 part_dir
= NetPartSelect::PV
;
2484 if (debug_elaborate
)
2485 cerr
<< get_line() << ": debug: "
2486 << "Elaborate lnet part select "
2489 << " wid=" << subnet_wid
<<"]"
2492 NetNet
*subsig
= new NetNet(sig
->scope(),
2493 sig
->scope()->local_symbol(),
2494 NetNet::WIRE
, subnet_wid
);
2495 subsig
->data_type( sig
->data_type() );
2496 subsig
->local_flag(true);
2497 subsig
->set_line(*this);
2499 NetPartSelect
*sub
= new NetPartSelect(sig
, lidx
, subnet_wid
,
2502 connect(sub
->pin(0), subsig
->pin(0));
2511 * Identifiers in continuous assignment l-values are limited to wires
2512 * and that ilk. Detect registers and memories here and report errors.
2514 NetNet
* PEIdent::elaborate_lnet(Design
*des
, NetScope
*scope
,
2515 bool implicit_net_ok
) const
2517 return elaborate_lnet_common_(des
, scope
, implicit_net_ok
, false);
2520 NetNet
* PEIdent::elaborate_bi_net(Design
*des
, NetScope
*scope
) const
2522 return elaborate_lnet_common_(des
, scope
, true, true);
2526 * This method is used to elaborate identifiers that are ports to a
2527 * scope. The scope is presumed to be that of the module that has the
2528 * port. This elaboration is done inside the module, and is only done
2529 * to PEIdent objects. This method is used by elaboration of a module
2530 * instantiation (PGModule::elaborate_mod_) to get NetNet objects for
2533 NetNet
* PEIdent::elaborate_port(Design
*des
, NetScope
*scope
) const
2535 NetNet
*sig
= des
->find_signal(scope
, path_
);
2537 cerr
<< get_line() << ": error: no wire/reg " << path_
2538 << " in module " << scope_path(scope
) << "." << endl
;
2543 /* Check the port_type of the signal to make sure it is really
2544 a port, and its direction is resolved. */
2545 switch (sig
->port_type()) {
2546 case NetNet::PINPUT
:
2547 case NetNet::POUTPUT
:
2548 case NetNet::PINOUT
:
2551 /* If the name matches, but the signal is not a port,
2552 then the user declared the object but there is no
2553 matching input/output/inout declaration. */
2555 case NetNet::NOT_A_PORT
:
2556 cerr
<< get_line() << ": error: signal " << path_
<< " in"
2557 << " module " << scope_path(scope
) << " is not a port." << endl
;
2558 cerr
<< get_line() << ": : Are you missing an input/"
2559 << "output/inout declaration?" << endl
;
2563 /* This should not happen. A PWire can only become
2564 PIMPLICIT if this is a udp reg port, and the make_udp
2565 function should turn it into an output.... I think. */
2567 case NetNet::PIMPLICIT
:
2568 cerr
<< get_line() << ": internal error: signal " << path_
2569 << " in module " << scope_path(scope
) << " is left as "
2570 << "port type PIMPLICIT." << endl
;
2578 /* Evaluate the part/bit select expressions, to get the part
2579 select of the signal that attaches to the port. Also handle
2580 range and direction checking here. */
2582 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
2586 unsigned swid
= midx
- lidx
+ 1;
2588 if (swid
< sig
->vector_width()) {
2589 cerr
<< get_line() << ": XXXX: Forgot to implement part select"
2590 << " of signal port." << endl
;
2597 * Elaborate a number as a NetConst object.
2599 * The code assumes that the result is IVL_VT_LOGIC.
2601 NetNet
* PENumber::elaborate_net(Design
*des
, NetScope
*scope
,
2603 const NetExpr
* rise
,
2604 const NetExpr
* fall
,
2605 const NetExpr
* decay
,
2606 Link::strength_t drive0
,
2607 Link::strength_t drive1
) const
2610 /* If we are constrained by a l-value size, then just make a
2611 number constant with the correct size and set as many bits
2612 in that constant as make sense. Pad excess with
2613 zeros. Also, assume that numbers are meant to be logic
2617 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2618 NetNet::IMPLICIT
, lwidth
);
2619 net
->data_type(IVL_VT_LOGIC
);
2620 net
->local_flag(true);
2621 net
->set_signed(value_
->has_sign());
2623 /* when expanding a constant to fit into the net, extend
2624 the Vx or Vz values if they are in the sign position,
2625 otherwise extend the number with 0 bits. */
2626 verinum::V top_v
= verinum::V0
;
2627 switch (value_
->get(value_
->len()-1)) {
2629 top_v
= verinum::Vx
;
2632 top_v
= verinum::Vz
;
2634 default: /* V0 and V1, do nothing */
2638 verinum
num(top_v
, net
->vector_width());
2640 for (idx
= 0 ; idx
< num
.len() && idx
< value_
->len(); idx
+= 1)
2641 num
.set(idx
, value_
->get(idx
));
2643 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2644 tmp
->pin(0).drive0(drive0
);
2645 tmp
->pin(0).drive1(drive1
);
2646 connect(net
->pin(0), tmp
->pin(0));
2652 /* If the number has a length, then use that to size the
2653 number. Generate a constant object of exactly the user
2655 if (value_
->has_len()) {
2656 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2657 NetNet::IMPLICIT
, value_
->len());
2658 net
->data_type(IVL_VT_LOGIC
);
2659 net
->local_flag(true);
2660 net
->set_signed(value_
->has_sign());
2661 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(),
2663 connect(net
->pin(0), tmp
->pin(0));
2669 /* None of the above tight constraints are present, so make a
2670 plausible choice for the width. Try to reduce the width as
2671 much as possible by eliminating high zeros of unsigned
2674 if (must_be_self_determined_flag
) {
2675 cerr
<< get_line() << ": error: No idea how wide to make "
2676 << "the unsized constant " << *value_
<< "." << endl
;
2680 unsigned width
= value_
->len();
2682 if (value_
->has_sign() && (value_
->get(width
-1) == verinum::V0
)) {
2684 /* If the number is signed, but known to be positive,
2685 then reduce it down as if it were unsigned. */
2687 if (value_
->get(width
-1) != verinum::V0
)
2692 } else if (value_
->has_sign() == false) {
2693 while ( (width
> 1) && (value_
->get(width
-1) == verinum::V0
))
2697 verinum
num (verinum::V0
, width
);
2698 for (unsigned idx
= 0 ; idx
< width
; idx
+= 1)
2699 num
.set(idx
, value_
->get(idx
));
2701 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2702 NetNet::IMPLICIT
, width
);
2703 net
->data_type(IVL_VT_LOGIC
);
2704 net
->local_flag(true);
2705 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2706 connect(net
->pin(0), tmp
->pin(0));
2713 * A string is a NetEConst node that is made of the ASCII bits of the
2714 * string instead of the bits of a number. In fact, a string is just
2715 * another numeric notation.
2717 NetNet
* PEString::elaborate_net(Design
*des
, NetScope
*scope
,
2719 const NetExpr
* rise
,
2720 const NetExpr
* fall
,
2721 const NetExpr
* decay
,
2722 Link::strength_t drive0
,
2723 Link::strength_t drive1
) const
2725 unsigned strbits
= strlen(text_
) * 8;
2728 /* If we are constrained by a l-value size, then just make a
2729 number constant with the correct size and set as many bits
2730 in that constant as make sense. Pad excess with zeros. */
2732 net
= new NetNet(scope
, scope
->local_symbol(),
2733 NetNet::IMPLICIT
, lwidth
);
2736 net
= new NetNet(scope
, scope
->local_symbol(),
2737 NetNet::IMPLICIT
, strbits
);
2739 net
->data_type(IVL_VT_BOOL
);
2740 net
->local_flag(true);
2742 /* Make a verinum that is filled with the 0 pad. */
2743 verinum
num(verinum::V0
, net
->vector_width());
2746 for (idx
= 0 ; idx
< num
.len() && idx
< strbits
; idx
+= 1) {
2747 char byte
= text_
[strbits
/8 - 1 - idx
/8];
2748 char mask
= 1<<(idx
%8);
2749 num
.set(idx
, (byte
& mask
)? verinum::V1
: verinum::V0
);
2752 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2753 tmp
->set_line(*this);
2756 connect(net
->pin(0), tmp
->pin(0));
2762 * Elaborate the ternary operator in a netlist by creating a LPM_MUX
2763 * with width matching the result, size == 2 and 1 select input. These
2764 * expressions come from code like:
2766 * res = test ? a : b;
2768 * The res has the width requested of this method, and the a and b
2769 * expressions have their own similar widths. The test expression is
2770 * only a single bit wide. The output from this function is a NetNet
2771 * object the width of the <res> expression and connected to the
2772 * Result pins of the LPM_MUX device. Any width not covered by the
2773 * width of the mux is padded with a NetConst device.
2775 NetNet
* PETernary::elaborate_net(Design
*des
, NetScope
*scope
,
2777 const NetExpr
* rise
,
2778 const NetExpr
* fall
,
2779 const NetExpr
* decay
,
2780 Link::strength_t drive0
,
2781 Link::strength_t drive1
) const
2783 NetNet
* expr_sig
= expr_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
2784 NetNet
* tru_sig
= tru_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
2785 NetNet
* fal_sig
= fal_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
2786 if (expr_sig
== 0 || tru_sig
== 0 || fal_sig
== 0) {
2791 /* The type of the true and false expressions must
2792 match. These become the type of the resulting
2795 ivl_variable_type_t expr_type
= tru_sig
->data_type();
2797 if (tru_sig
->data_type() != fal_sig
->data_type()) {
2798 cerr
<< get_line() << ": error: True and False clauses of"
2799 << " ternary expression have differnt types." << endl
;
2800 cerr
<< get_line() << ": : True clause is "
2801 << tru_sig
->data_type() << ", false clause is "
2802 << fal_sig
->data_type() << "." << endl
;
2805 expr_type
= IVL_VT_NO_TYPE
;
2807 } else if (expr_type
== IVL_VT_NO_TYPE
) {
2808 cerr
<< get_line() << ": internal error: True and false "
2809 << "clauses of ternary both have NO TYPE." << endl
;
2813 /* The natural width of the expression is the width of the
2814 largest condition. Normally they should be the same size,
2815 but if we do not get a size from the context, or the
2816 expressions resist, we need to cope. */
2817 unsigned iwidth
= tru_sig
->vector_width();
2818 if (fal_sig
->vector_width() > iwidth
)
2819 iwidth
= fal_sig
->vector_width();
2822 /* If the width is not passed from the context, then take the
2823 widest result as our width. */
2827 /* If the expression has width, then generate a boolean result
2828 by connecting an OR gate to calculate the truth value of
2829 the result. In the end, the result needs to be a single bit. */
2830 if (expr_sig
->vector_width() > 1) {
2831 NetUReduce
*log
= new NetUReduce(scope
, scope
->local_symbol(),
2833 expr_sig
->vector_width());
2834 log
->set_line(*this);
2836 connect(log
->pin(1), expr_sig
->pin(0));
2838 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2839 NetNet::IMPLICIT
, 1);
2840 tmp
->data_type(IVL_VT_LOGIC
);
2841 tmp
->local_flag(true);
2842 connect(log
->pin(0), tmp
->pin(0));
2847 assert(expr_sig
->vector_width() == 1);
2849 /* This is the width of the LPM_MUX device that I'm about to
2850 create. It may be smaller then the desired output, but I'll
2851 handle padding below. Note that in principle the
2852 alternatives should be padded to the output width first,
2853 but it is more efficient to pad them only just enough to
2854 prevent loss, and do the finished padding later.
2856 Create a NetNet object wide enough to hold the
2857 result. Also, pad the result values (if necessary) so that
2858 the mux inputs can be fully connected. */
2860 unsigned dwidth
= (iwidth
> width
)? width
: iwidth
;
2862 NetNet
*sig
= new NetNet(scope
, scope
->local_symbol(),
2863 NetNet::WIRE
, dwidth
);
2864 sig
->data_type(expr_type
);
2865 sig
->local_flag(true);
2867 if (fal_sig
->vector_width() < dwidth
)
2868 fal_sig
= pad_to_width(des
, fal_sig
, dwidth
);
2870 if (tru_sig
->vector_width() < dwidth
)
2871 tru_sig
= pad_to_width(des
, tru_sig
, dwidth
);
2873 if (dwidth
< fal_sig
->vector_width())
2874 fal_sig
= crop_to_width(des
, fal_sig
, dwidth
);
2876 if (dwidth
< tru_sig
->vector_width())
2877 tru_sig
= crop_to_width(des
, tru_sig
, dwidth
);
2879 /* Make the device and connect its outputs to the osig and
2880 inputs to the tru and false case nets. Also connect the
2881 selector bit to the sel input.
2883 The inputs are the 0 (false) connected to fal_sig and 1
2884 (true) connected to tru_sig. */
2886 NetMux
*mux
= new NetMux(scope
, scope
->local_symbol(), dwidth
, 2, 1);
2887 connect(mux
->pin_Sel(), expr_sig
->pin(0));
2889 /* Connect the data inputs. */
2890 connect(mux
->pin_Data(0), fal_sig
->pin(0));
2891 connect(mux
->pin_Data(1), tru_sig
->pin(0));
2893 /* If there are non-zero output delays, then create bufz
2894 devices to carry the propagation delays. Otherwise, just
2895 connect the result to the output. */
2896 if (rise
|| fall
|| decay
) {
2897 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2898 NetNet::WIRE
, dwidth
);
2899 tmp
->data_type(expr_type
);
2900 tmp
->local_flag(true);
2902 NetBUFZ
*tmpz
= new NetBUFZ(scope
, scope
->local_symbol(), dwidth
);
2903 tmpz
->rise_time(rise
);
2904 tmpz
->fall_time(fall
);
2905 tmpz
->decay_time(decay
);
2906 tmpz
->pin(0).drive0(drive0
);
2907 tmpz
->pin(0).drive1(drive1
);
2909 connect(mux
->pin_Result(), tmp
->pin(0));
2910 connect(tmp
->pin(0), tmpz
->pin(1));
2911 connect(sig
->pin(0), tmpz
->pin(0));
2913 des
->add_node(tmpz
);
2916 connect(mux
->pin_Result(), sig
->pin(0));
2919 /* If the MUX device result is too narrow to fill out the
2920 desired result, pad with zeros... */
2921 assert(dwidth
<= width
);
2925 /* If the MUX device results is too narrow to fill out the
2926 desired result, then pad it. It is OK to have a too-narrow
2927 result here because the dwidth choice is >= the width of
2928 both alternatives. Thus, padding here is equivalent to
2929 padding inside, and is cheaper. */
2931 sig
= pad_to_width(des
, sig
, width
);
2936 NetNet
* PEUnary::elaborate_net(Design
*des
, NetScope
*scope
,
2938 const NetExpr
* rise
,
2939 const NetExpr
* fall
,
2940 const NetExpr
* decay
,
2941 Link::strength_t drive0
,
2942 Link::strength_t drive1
) const
2945 // Some unary operands allow the operand to be
2946 // self-determined, and some do not.
2947 unsigned owidth
= 0;
2959 // Handle the special case of a 2's complement of a constant
2960 // value. This can be reduced to a no-op on a precalculated
2962 if (op_
== '-') do {
2963 // TODO: Should replace this with a call to
2964 // elab_and_eval. Possibly blend this with the rest of
2965 // the elaboration as well.
2966 verinum
*val
= expr_
->eval_const(des
, scope
);
2974 sig
= new NetNet(scope
, scope
->local_symbol(),
2975 NetNet::WIRE
, width
);
2976 sig
->data_type(IVL_VT_LOGIC
);
2977 sig
->local_flag(true);
2979 /* Take the 2s complement by taking the 1s complement
2981 verinum
tmp (v_not(*val
), width
);
2982 verinum
one (1UL, width
);
2983 tmp
= verinum(tmp
+ one
, width
);
2984 tmp
.has_sign(val
->has_sign());
2986 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(), tmp
);
2987 connect(sig
->pin(0), con
->pin(0));
2989 if (debug_elaborate
) {
2990 cerr
<< get_line() << ": debug: Replace expression "
2991 << *this << " with constant " << tmp
<< "."<<endl
;
3000 NetNet
* sub_sig
= expr_
->elaborate_net(des
, scope
, owidth
, 0, 0, 0);
3007 bool reduction
=false;
3008 NetUReduce::TYPE rtype
= NetUReduce::NONE
;
3011 case '~': // Bitwise NOT
3012 sig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
,
3013 sub_sig
->vector_width());
3014 sig
->data_type(sub_sig
->data_type());
3015 sig
->local_flag(true);
3016 gate
= new NetLogic(scope
, scope
->local_symbol(),
3017 2, NetLogic::NOT
, sub_sig
->vector_width());
3018 gate
->set_line(*this);
3019 des
->add_node(gate
);
3020 gate
->rise_time(rise
);
3021 gate
->fall_time(fall
);
3022 gate
->decay_time(decay
);
3024 connect(gate
->pin(1), sub_sig
->pin(0));
3025 connect(gate
->pin(0), sig
->pin(0));
3028 case 'N': // Reduction NOR
3029 case '!': // Reduction NOT
3030 reduction
=true; rtype
= NetUReduce::NOR
; break;
3031 case '&': // Reduction AND
3032 reduction
=true; rtype
= NetUReduce::AND
; break;
3033 case '|': // Reduction OR
3034 reduction
=true; rtype
= NetUReduce::OR
; break;
3035 case '^': // Reduction XOR
3036 reduction
=true; rtype
= NetUReduce::XOR
; break;
3037 case 'A': // Reduction NAND (~&)
3038 reduction
=true; rtype
= NetUReduce::NAND
; break;
3039 case 'X': // Reduction XNOR (~^)
3040 reduction
=true; rtype
= NetUReduce::XNOR
; break;
3042 case '-': // Unary 2's complement.
3043 // If this expression is self determined, get its width
3044 // from the sub_expression.
3046 owidth
= sub_sig
->vector_width();
3048 sig
= new NetNet(scope
, scope
->local_symbol(),
3049 NetNet::WIRE
, owidth
);
3050 sig
->data_type(sub_sig
->data_type());
3051 sig
->local_flag(true);
3053 if (sub_sig
->vector_width() < owidth
)
3054 sub_sig
= pad_to_width(des
, sub_sig
, owidth
);
3056 switch (sub_sig
->vector_width()) {
3062 gate
= new NetLogic(scope
, scope
->local_symbol(),
3063 2, NetLogic::BUF
, 1);
3064 connect(gate
->pin(0), sig
->pin(0));
3065 connect(gate
->pin(1), sub_sig
->pin(0));
3066 des
->add_node(gate
);
3067 gate
->rise_time(rise
);
3068 gate
->fall_time(fall
);
3069 gate
->decay_time(decay
);
3073 NetAddSub
*sub
= new NetAddSub(scope
, scope
->local_symbol(),
3074 sig
->vector_width());
3075 sub
->attribute(perm_string::literal("LPM_Direction"),
3080 connect(sig
->pin(0), sub
->pin_Result());
3081 connect(sub_sig
->pin(0), sub
->pin_DataB());
3083 verinum
tmp_num (verinum::V0
, sub
->width(), true);
3084 NetConst
*tmp_con
= new NetConst(scope
,
3085 scope
->local_symbol(),
3087 des
->add_node(tmp_con
);
3089 NetNet
*tmp_sig
= new NetNet(scope
, scope
->local_symbol(),
3091 sub_sig
->vector_width());
3092 tmp_sig
->data_type(sub_sig
->data_type());
3093 tmp_sig
->local_flag(true);
3095 connect(tmp_sig
->pin(0), sub
->pin_DataA());
3096 connect(tmp_sig
->pin(0), tmp_con
->pin(0));
3102 cerr
<< "internal error: Unhandled UNARY '" << op_
<< "'" << endl
;
3109 // The output of a reduction operator is 1 bit
3110 sig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
, 1);
3111 sig
->data_type(sub_sig
->data_type());
3112 sig
->local_flag(true);
3114 rgate
= new NetUReduce(scope
, scope
->local_symbol(),
3115 rtype
, sub_sig
->vector_width());
3116 rgate
->set_line(*this);
3117 connect(rgate
->pin(0), sig
->pin(0));
3118 connect(rgate
->pin(1), sub_sig
->pin(0));
3120 des
->add_node(rgate
);
3121 rgate
->rise_time(rise
);
3122 rgate
->fall_time(fall
);
3123 rgate
->decay_time(decay
);
3130 * $Log: elab_net.cc,v $
3131 * Revision 1.207 2007/06/12 04:05:45 steve
3132 * Put instantiated modules in the proper generated scope.
3134 * Revision 1.206 2007/06/04 02:19:07 steve
3135 * Handle bit/part select of array words in nets.
3137 * Revision 1.205 2007/06/02 03:42:12 steve
3138 * Properly evaluate scope path expressions.
3140 * Revision 1.204 2007/05/24 04:07:11 steve
3141 * Rework the heirarchical identifier parse syntax and pform
3142 * to handle more general combinations of heirarch and bit selects.
3144 * Revision 1.203 2007/04/18 01:40:49 steve
3145 * Fix elaboration of multiply of two constants.
3147 * Revision 1.202 2007/04/17 04:18:10 steve
3148 * Support part select of array words in net contexts.
3150 * Revision 1.201 2007/03/22 16:08:14 steve
3151 * Spelling fixes from Larry
3153 * Revision 1.200 2007/02/27 06:10:16 steve
3154 * Better error message around repeat concatenation syntax.
3156 * Revision 1.199 2007/02/26 19:49:48 steve
3157 * Spelling fixes (larry doolittle)
3159 * Revision 1.198 2007/02/05 01:42:31 steve
3160 * Set some missing local flags.
3162 * Revision 1.197 2007/02/01 19:06:06 steve
3163 * Ternary output node is local.
3165 * Revision 1.196 2007/02/01 03:14:33 steve
3166 * Detect and report arrays without index in net contexts.
3168 * Revision 1.195 2007/01/31 04:21:10 steve
3169 * Add method to bind assertions to verilog source lines.
3171 * Revision 1.194 2007/01/20 02:10:45 steve
3172 * Get argument widths right for shift results.
3174 * Revision 1.193 2007/01/19 04:26:24 steve
3175 * Fix missing data_type mark for array words.
3177 * Revision 1.192 2007/01/16 05:44:15 steve
3178 * Major rework of array handling. Memories are replaced with the
3179 * more general concept of arrays. The NetMemory and NetEMemory
3180 * classes are removed from the ivl core program, and the IVL_LPM_RAM
3181 * lpm type is removed from the ivl_target API.
3183 * Revision 1.191 2006/12/08 03:43:26 steve
3184 * Prevent name clash when processing parameter in net.
3186 * Revision 1.190 2006/11/26 06:29:16 steve
3187 * Fix nexus widths for direct link assign and ternary nets.
3189 * Revision 1.189 2006/08/08 05:11:37 steve
3190 * Handle 64bit delay constants.
3192 * Revision 1.188 2006/06/20 05:06:47 steve
3193 * Sign extend operands of signed addition.
3195 * Revision 1.187 2006/06/18 04:15:50 steve
3196 * Add support for system functions in continuous assignments.
3198 * Revision 1.186 2006/06/02 04:48:50 steve
3199 * Make elaborate_expr methods aware of the width that the context
3200 * requires of it. In the process, fix sizing of the width of unary
3201 * minus is context determined sizes.
3203 * Revision 1.185 2006/05/19 04:44:55 steve
3204 * Get self-determined unary - width right.
3206 * Revision 1.184 2006/05/01 20:47:58 steve
3207 * More explicit datatype setup.
3209 * Revision 1.183 2006/04/30 05:17:48 steve
3210 * Get the data type of part select results right.
3212 * Revision 1.182 2006/04/28 05:09:51 steve
3213 * Handle padding of MUX net results.
3215 * Revision 1.181 2006/04/28 04:28:35 steve
3216 * Allow concatenations as arguments to inout ports.
3218 * Revision 1.180 2006/04/24 05:15:07 steve
3219 * Fix support for indexed part select in continuous assign l-values.
3221 * Revision 1.179 2006/04/10 00:32:14 steve
3222 * Clean up index expression error message.
3224 * Revision 1.178 2006/02/02 02:43:57 steve
3225 * Allow part selects of memory words in l-values.
3227 * Revision 1.177 2006/01/02 05:33:19 steve
3228 * Node delays can be more general expressions in structural contexts.
3230 * Revision 1.176 2005/10/11 16:15:52 steve
3231 * Logical or/and return VT_LOGIC type.
3233 * Revision 1.175 2005/09/19 15:21:09 steve
3234 * Fix data type of parameters to logic.
3236 * Revision 1.174 2005/09/15 23:04:09 steve
3237 * Make sure div, mod and mult nodes have line number info.
3239 * Revision 1.173 2005/09/14 15:15:44 steve
3240 * fit type elaboration of logical not.
3242 * Revision 1.172 2005/09/01 04:10:47 steve
3243 * Check operand types for compatibility.
3245 * Revision 1.171 2005/08/31 05:07:31 steve
3246 * Handle memory references is continuous assignments.
3248 * Revision 1.170 2005/08/06 17:58:16 steve
3249 * Implement bi-directional part selects.
3251 * Revision 1.169 2005/07/15 04:13:25 steve
3252 * Match data type of PV select input/output.
3254 * Revision 1.168 2005/07/15 00:42:02 steve
3255 * Get output type correct for binary mux (ternary) expression.
3257 * Revision 1.167 2005/07/11 16:56:50 steve
3258 * Remove NetVariable and ivl_variable_t structures.
3260 * Revision 1.166 2005/07/07 16:22:49 steve
3261 * Generalize signals to carry types.
3263 * Revision 1.165 2005/05/24 01:44:27 steve
3264 * Do sign extension of structuran nets.
3266 * Revision 1.164 2005/05/19 03:51:38 steve
3267 * Make sure comparison widths match.
3269 * Revision 1.163 2005/05/10 05:10:40 steve
3270 * Make sig-eq-constant optimization more effective.
3272 * Revision 1.162 2005/05/08 23:44:08 steve
3273 * Add support for variable part select.
3275 * Revision 1.161 2005/05/06 00:25:13 steve
3276 * Handle synthesis of concatenation expressions.
3278 * Revision 1.160 2005/04/08 04:52:31 steve
3279 * Make clear that memory addresses are cannonical.
3281 * Revision 1.159 2005/04/06 05:29:08 steve
3282 * Rework NetRamDq and IVL_LPM_RAM nodes.
3284 * Revision 1.158 2005/03/19 06:59:53 steve
3285 * Handle wide operands to logical AND.
3287 * Revision 1.157 2005/03/19 06:23:49 steve
3288 * Handle LPM shifts.
3290 * Revision 1.156 2005/03/18 02:56:03 steve
3291 * Add support for LPM_UFUNC user defined functions.
3293 * Revision 1.155 2005/03/13 01:26:48 steve
3294 * UPdate elabrate continuous assighn of string to net.
3296 * Revision 1.154 2005/03/12 06:43:35 steve
3297 * Update support for LPM_MOD.
3299 * Revision 1.153 2005/03/09 05:52:03 steve
3300 * Handle case inequality in netlists.
3302 * Revision 1.152 2005/02/19 02:43:38 steve
3303 * Support shifts and divide.
3305 * Revision 1.151 2005/02/12 06:25:40 steve
3306 * Restructure NetMux devices to pass vectors.
3307 * Generate NetMux devices from ternary expressions,
3308 * Reduce NetMux devices to bufif when appropriate.
3310 * Revision 1.150 2005/02/03 04:56:20 steve
3311 * laborate reduction gates into LPM_RED_ nodes.
3313 * Revision 1.149 2005/01/30 05:20:38 steve
3314 * Elaborate unary subtract and NOT in netlist
3315 * contexts, and concatenation too.
3317 * Revision 1.148 2005/01/29 18:46:18 steve
3318 * Netlist boolean expressions generate gate vectors.
3320 * Revision 1.147 2005/01/29 16:46:22 steve
3321 * Elaborate parameter reference to desired width without concats.
3323 * Revision 1.146 2005/01/29 00:37:06 steve
3324 * Integrate pr1072 fix from v0_8-branch.
3326 * Revision 1.145 2005/01/28 05:39:33 steve
3327 * Simplified NetMult and IVL_LPM_MULT.
3329 * Revision 1.144 2005/01/22 18:16:00 steve
3330 * Remove obsolete NetSubnet class.
3332 * Revision 1.143 2005/01/22 01:06:55 steve
3333 * Change case compare from logic to an LPM node.
3335 * Revision 1.142 2005/01/16 04:20:32 steve
3336 * Implement LPM_COMPARE nodes as two-input vector functors.
3338 * Revision 1.141 2005/01/13 00:23:10 steve
3339 * Fix elaboration of == compared to constants.
3341 * Revision 1.140 2005/01/09 20:16:00 steve
3342 * Use PartSelect/PV and VP to handle part selects through ports.
3344 * Revision 1.139 2004/12/11 02:31:25 steve
3345 * Rework of internals to carry vectors through nexus instead
3346 * of single bits. Make the ivl, tgt-vvp and vvp initial changes
3349 * Revision 1.138 2004/10/04 03:09:38 steve
3350 * Fix excessive error message.
3352 * Revision 1.137 2004/10/04 01:10:52 steve
3353 * Clean up spurious trailing white space.
3355 * Revision 1.136 2004/10/04 00:25:46 steve
3356 * Error message to match assertion.