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
);
2246 cerr
<< get_line() << ": error: indexed part select of "
2248 << " must be a constant in this context." << endl
;
2253 long midx_val
= tmp
->value().as_long();
2254 midx
= sig
->sb_to_idx(midx_val
);
2257 /* The width (a constant) is calculated here. */
2258 unsigned long wid
= 0;
2259 bool flag
= calculate_up_do_width_(des
, scope
, wid
);
2263 if (index_tail
.sel
== index_component_t::SEL_IDX_UP
)
2264 lidx
= sig
->sb_to_idx(midx_val
+wid
-1);
2266 lidx
= sig
->sb_to_idx(midx_val
-wid
+1);
2277 case index_component_t::SEL_PART
: {
2280 bool flag
= calculate_parts_(des
, scope
, msb
, lsb
);
2282 NetExpr
*tmp_ex
= elab_and_eval(des
, scope
, index_tail
.msb
, -1);
2283 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2286 long midx_val
= tmp
->value().as_long();
2287 midx
= sig
->sb_to_idx(midx_val
);
2290 tmp_ex
= elab_and_eval(des
, scope
, index_tail
.lsb
, -1);
2291 tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2293 cerr
<< get_line() << ": internal error: "
2294 << "lsb expression is not constant?: "
2295 << *tmp_ex
<< ", " << *index_tail
.lsb
<< endl
;
2299 long lidx_val
= tmp
->value().as_long();
2300 lidx
= sig
->sb_to_idx(lidx_val
);
2303 lidx
= sig
->sb_to_idx(lsb
);
2304 midx
= sig
->sb_to_idx(msb
);
2305 /* Detect reversed indices of a part select. */
2307 cerr
<< get_line() << ": error: Part select "
2308 << sig
->name() << "[" << msb
<< ":"
2309 << lsb
<< "] indices reversed." << endl
;
2310 cerr
<< get_line() << ": : Did you mean "
2311 << sig
->name() << "[" << lsb
<< ":"
2312 << msb
<< "]?" << endl
;
2313 unsigned tmp
= midx
;
2319 /* Detect a part select out of range. */
2320 if (midx
>= sig
->vector_width()) {
2321 cerr
<< get_line() << ": error: Part select "
2322 << sig
->name() << "[" << msb
<< ":"
2323 << lsb
<< "] out of range." << endl
;
2324 midx
= sig
->vector_width() - 1;
2331 case index_component_t::SEL_BIT
:
2332 if (name_tail
.index
.size() > sig
->array_dimensions()) {
2333 verinum
*mval
= index_tail
.msb
->eval_const(des
, scope
);
2335 cerr
<< get_line() << ": error: Index of " << path_
<<
2336 " needs to be constant in this context." <<
2338 cerr
<< get_line() << ": : Index expression is: "
2339 << *index_tail
.msb
<< endl
;
2340 cerr
<< get_line() << ": : Context scope is: "
2341 << scope_path(scope
) << endl
;
2347 midx
= sig
->sb_to_idx(mval
->as_long());
2348 if (midx
>= sig
->vector_width()) {
2349 cerr
<< get_line() << ": error: Index " << sig
->name()
2350 << "[" << mval
->as_long() << "] out of range."
2358 cerr
<< get_line() << ": internal error: "
2359 << "Bit select " << path_
<< endl
;
2360 ivl_assert(*this, 0);
2361 midx
= sig
->vector_width() - 1;
2371 * This is the common code for l-value nets and bi-directional
2372 * nets. There is very little that is different between the two cases,
2373 * so most of the work for both is done here.
2375 NetNet
* PEIdent::elaborate_lnet_common_(Design
*des
, NetScope
*scope
,
2376 bool implicit_net_ok
,
2377 bool bidirectional_flag
) const
2382 const NetExpr
*par
= 0;
2385 symbol_search(des
, scope
, path_
, sig
, par
, eve
);
2388 cerr
<< get_line() << ": error: named events (" << path_
2389 << ") cannot be l-values in continuous "
2390 << "assignments." << endl
;
2397 if (implicit_net_ok
) {
2399 sig
= make_implicit_net_(des
, scope
);
2404 cerr
<< get_line() << ": error: Net " << path_
2405 << " is not defined in this context." << endl
;
2413 /* Don't allow registers as assign l-values. */
2414 if (sig
->type() == NetNet::REG
) {
2415 cerr
<< get_line() << ": error: reg " << sig
->name()
2416 << "; cannot be driven by primitives"
2417 << " or continuous assignment." << endl
;
2422 if (sig
->port_type() == NetNet::PINPUT
) {
2423 cerr
<< get_line() << ": warning: L-value ``"
2424 << sig
->name() << "'' is also an input port." << endl
;
2425 cerr
<< sig
->get_line() << ": warning: input "
2426 << sig
->name() << "; is coerced to inout." << endl
;
2427 sig
->port_type(NetNet::PINOUT
);
2430 // Default part select is the entire word.
2431 unsigned midx
= sig
->vector_width()-1, lidx
= 0;
2432 // The default word select is the first.
2435 const name_component_t
&name_tail
= path_
.back();
2437 if (sig
->array_dimensions() > 0) {
2439 if (name_tail
.index
.empty()) {
2440 cerr
<< get_line() << ": error: array " << sig
->name()
2441 << " must be used with an index." << endl
;
2446 const index_component_t
&index_head
= name_tail
.index
.front();
2447 if (index_head
.sel
== index_component_t::SEL_PART
) {
2448 cerr
<< get_line() << ": error: cannot perform a part "
2449 << "select on array " << sig
->name() << "." << endl
;
2453 ivl_assert(*this, index_head
.sel
== index_component_t::SEL_BIT
);
2455 NetExpr
*tmp_ex
= elab_and_eval(des
, scope
, index_head
.msb
, -1);
2456 NetEConst
*tmp
= dynamic_cast<NetEConst
*>(tmp_ex
);
2458 cerr
<< get_line() << ": error: array " << sig
->name()
2459 << " index must be a constant in this context." << endl
;
2464 long widx_val
= tmp
->value().as_long();
2465 widx
= sig
->array_index_to_address(widx_val
);
2468 if (debug_elaborate
)
2469 cerr
<< get_line() << ": debug: Use [" << widx
<< "]"
2470 << " to index l-value array." << endl
;
2472 /* The array has a part/bit select at the end. */
2473 if (name_tail
.index
.size() > sig
->array_dimensions()) {
2474 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
2477 } else if (!name_tail
.index
.empty()) {
2478 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
2482 unsigned subnet_wid
= midx
-lidx
+1;
2484 if (sig
->pin_count() > 1) {
2485 assert(widx
< sig
->pin_count());
2487 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2488 sig
->type(), sig
->vector_width());
2489 tmp
->set_line(*this);
2490 tmp
->local_flag(true);
2491 connect(sig
->pin(widx
), tmp
->pin(0));
2495 /* If the desired l-value vector is narrower then the
2496 signal itself, then use a NetPartSelect node to
2497 arrange for connection to the desired bits. All this
2498 can be skipped if the desired with matches the
2501 if (subnet_wid
!= sig
->vector_width()) {
2502 /* If we are processing a tran or inout, then the
2503 partselect is bi-directional. Otherwise, it is a
2504 Part-to-Vector select. */
2505 NetPartSelect::dir_t part_dir
;
2506 if (bidirectional_flag
)
2507 part_dir
= NetPartSelect::BI
;
2509 part_dir
= NetPartSelect::PV
;
2511 if (debug_elaborate
)
2512 cerr
<< get_line() << ": debug: "
2513 << "Elaborate lnet part select "
2516 << " wid=" << subnet_wid
<<"]"
2519 NetNet
*subsig
= new NetNet(sig
->scope(),
2520 sig
->scope()->local_symbol(),
2521 NetNet::WIRE
, subnet_wid
);
2522 subsig
->data_type( sig
->data_type() );
2523 subsig
->local_flag(true);
2524 subsig
->set_line(*this);
2526 NetPartSelect
*sub
= new NetPartSelect(sig
, lidx
, subnet_wid
,
2529 connect(sub
->pin(0), subsig
->pin(0));
2538 * Identifiers in continuous assignment l-values are limited to wires
2539 * and that ilk. Detect registers and memories here and report errors.
2541 NetNet
* PEIdent::elaborate_lnet(Design
*des
, NetScope
*scope
,
2542 bool implicit_net_ok
) const
2544 return elaborate_lnet_common_(des
, scope
, implicit_net_ok
, false);
2547 NetNet
* PEIdent::elaborate_bi_net(Design
*des
, NetScope
*scope
) const
2549 return elaborate_lnet_common_(des
, scope
, true, true);
2553 * This method is used to elaborate identifiers that are ports to a
2554 * scope. The scope is presumed to be that of the module that has the
2555 * port. This elaboration is done inside the module, and is only done
2556 * to PEIdent objects. This method is used by elaboration of a module
2557 * instantiation (PGModule::elaborate_mod_) to get NetNet objects for
2560 NetNet
* PEIdent::elaborate_port(Design
*des
, NetScope
*scope
) const
2562 NetNet
*sig
= des
->find_signal(scope
, path_
);
2564 cerr
<< get_line() << ": error: no wire/reg " << path_
2565 << " in module " << scope_path(scope
) << "." << endl
;
2570 /* Check the port_type of the signal to make sure it is really
2571 a port, and its direction is resolved. */
2572 switch (sig
->port_type()) {
2573 case NetNet::PINPUT
:
2574 case NetNet::POUTPUT
:
2575 case NetNet::PINOUT
:
2578 /* If the name matches, but the signal is not a port,
2579 then the user declared the object but there is no
2580 matching input/output/inout declaration. */
2582 case NetNet::NOT_A_PORT
:
2583 cerr
<< get_line() << ": error: signal " << path_
<< " in"
2584 << " module " << scope_path(scope
) << " is not a port." << endl
;
2585 cerr
<< get_line() << ": : Are you missing an input/"
2586 << "output/inout declaration?" << endl
;
2590 /* This should not happen. A PWire can only become
2591 PIMPLICIT if this is a udp reg port, and the make_udp
2592 function should turn it into an output.... I think. */
2594 case NetNet::PIMPLICIT
:
2595 cerr
<< get_line() << ": internal error: signal " << path_
2596 << " in module " << scope_path(scope
) << " is left as "
2597 << "port type PIMPLICIT." << endl
;
2605 /* Evaluate the part/bit select expressions, to get the part
2606 select of the signal that attaches to the port. Also handle
2607 range and direction checking here. */
2609 if (! eval_part_select_(des
, scope
, sig
, midx
, lidx
))
2613 unsigned swid
= midx
- lidx
+ 1;
2615 if (swid
< sig
->vector_width()) {
2616 cerr
<< get_line() << ": XXXX: Forgot to implement part select"
2617 << " of signal port." << endl
;
2624 * Elaborate a number as a NetConst object.
2626 * The code assumes that the result is IVL_VT_LOGIC.
2628 NetNet
* PENumber::elaborate_net(Design
*des
, NetScope
*scope
,
2630 const NetExpr
* rise
,
2631 const NetExpr
* fall
,
2632 const NetExpr
* decay
,
2633 Link::strength_t drive0
,
2634 Link::strength_t drive1
) const
2637 /* If we are constrained by a l-value size, then just make a
2638 number constant with the correct size and set as many bits
2639 in that constant as make sense. Pad excess with
2640 zeros. Also, assume that numbers are meant to be logic
2644 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2645 NetNet::IMPLICIT
, lwidth
);
2646 net
->data_type(IVL_VT_LOGIC
);
2647 net
->local_flag(true);
2648 net
->set_signed(value_
->has_sign());
2650 verinum num
= pad_to_width(*value_
, lwidth
);
2651 if (num
.len() > lwidth
)
2652 num
= verinum(num
, lwidth
);
2654 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2655 tmp
->pin(0).drive0(drive0
);
2656 tmp
->pin(0).drive1(drive1
);
2657 connect(net
->pin(0), tmp
->pin(0));
2663 /* If the number has a length, then use that to size the
2664 number. Generate a constant object of exactly the user
2666 if (value_
->has_len()) {
2667 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2668 NetNet::IMPLICIT
, value_
->len());
2669 net
->data_type(IVL_VT_LOGIC
);
2670 net
->local_flag(true);
2671 net
->set_signed(value_
->has_sign());
2672 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(),
2674 connect(net
->pin(0), tmp
->pin(0));
2680 /* None of the above tight constraints are present, so make a
2681 plausible choice for the width. Try to reduce the width as
2682 much as possible by eliminating high zeros of unsigned
2685 if (must_be_self_determined_flag
) {
2686 cerr
<< get_line() << ": error: No idea how wide to make "
2687 << "the unsized constant " << *value_
<< "." << endl
;
2691 unsigned width
= value_
->len();
2693 if (value_
->has_sign() && (value_
->get(width
-1) == verinum::V0
)) {
2695 /* If the number is signed, but known to be positive,
2696 then reduce it down as if it were unsigned. */
2698 if (value_
->get(width
-1) != verinum::V0
)
2703 } else if (value_
->has_sign() == false) {
2704 while ( (width
> 1) && (value_
->get(width
-1) == verinum::V0
))
2708 verinum
num (verinum::V0
, width
);
2709 for (unsigned idx
= 0 ; idx
< width
; idx
+= 1)
2710 num
.set(idx
, value_
->get(idx
));
2712 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
2713 NetNet::IMPLICIT
, width
);
2714 net
->data_type(IVL_VT_LOGIC
);
2715 net
->local_flag(true);
2716 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2717 connect(net
->pin(0), tmp
->pin(0));
2724 * A string is a NetEConst node that is made of the ASCII bits of the
2725 * string instead of the bits of a number. In fact, a string is just
2726 * another numeric notation.
2728 NetNet
* PEString::elaborate_net(Design
*des
, NetScope
*scope
,
2730 const NetExpr
* rise
,
2731 const NetExpr
* fall
,
2732 const NetExpr
* decay
,
2733 Link::strength_t drive0
,
2734 Link::strength_t drive1
) const
2736 unsigned strbits
= strlen(text_
) * 8;
2739 /* If we are constrained by a l-value size, then just make a
2740 number constant with the correct size and set as many bits
2741 in that constant as make sense. Pad excess with zeros. */
2743 net
= new NetNet(scope
, scope
->local_symbol(),
2744 NetNet::IMPLICIT
, lwidth
);
2747 net
= new NetNet(scope
, scope
->local_symbol(),
2748 NetNet::IMPLICIT
, strbits
);
2750 net
->data_type(IVL_VT_BOOL
);
2751 net
->local_flag(true);
2753 /* Make a verinum that is filled with the 0 pad. */
2754 verinum
num(verinum::V0
, net
->vector_width());
2757 for (idx
= 0 ; idx
< num
.len() && idx
< strbits
; idx
+= 1) {
2758 char byte
= text_
[strbits
/8 - 1 - idx
/8];
2759 char mask
= 1<<(idx
%8);
2760 num
.set(idx
, (byte
& mask
)? verinum::V1
: verinum::V0
);
2763 NetConst
*tmp
= new NetConst(scope
, scope
->local_symbol(), num
);
2764 tmp
->set_line(*this);
2767 connect(net
->pin(0), tmp
->pin(0));
2773 * Elaborate the ternary operator in a netlist by creating a LPM_MUX
2774 * with width matching the result, size == 2 and 1 select input. These
2775 * expressions come from code like:
2777 * res = test ? a : b;
2779 * The res has the width requested of this method, and the a and b
2780 * expressions have their own similar widths. The test expression is
2781 * only a single bit wide. The output from this function is a NetNet
2782 * object the width of the <res> expression and connected to the
2783 * Result pins of the LPM_MUX device. Any width not covered by the
2784 * width of the mux is padded with a NetConst device.
2786 NetNet
* PETernary::elaborate_net(Design
*des
, NetScope
*scope
,
2788 const NetExpr
* rise
,
2789 const NetExpr
* fall
,
2790 const NetExpr
* decay
,
2791 Link::strength_t drive0
,
2792 Link::strength_t drive1
) const
2794 NetNet
* expr_sig
= expr_
->elaborate_net(des
, scope
, 0, 0, 0, 0);
2795 NetNet
* tru_sig
= tru_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
2796 NetNet
* fal_sig
= fal_
->elaborate_net(des
, scope
, width
, 0, 0, 0);
2797 if (expr_sig
== 0 || tru_sig
== 0 || fal_sig
== 0) {
2802 /* The type of the true and false expressions must
2803 match. These become the type of the resulting
2806 ivl_variable_type_t expr_type
= tru_sig
->data_type();
2808 if (tru_sig
->data_type() != fal_sig
->data_type()) {
2809 cerr
<< get_line() << ": error: True and False clauses of"
2810 << " ternary expression have differnt types." << endl
;
2811 cerr
<< get_line() << ": : True clause is "
2812 << tru_sig
->data_type() << ", false clause is "
2813 << fal_sig
->data_type() << "." << endl
;
2816 expr_type
= IVL_VT_NO_TYPE
;
2818 } else if (expr_type
== IVL_VT_NO_TYPE
) {
2819 cerr
<< get_line() << ": internal error: True and false "
2820 << "clauses of ternary both have NO TYPE." << endl
;
2824 /* The natural width of the expression is the width of the
2825 largest condition. Normally they should be the same size,
2826 but if we do not get a size from the context, or the
2827 expressions resist, we need to cope. */
2828 unsigned iwidth
= tru_sig
->vector_width();
2829 if (fal_sig
->vector_width() > iwidth
)
2830 iwidth
= fal_sig
->vector_width();
2833 /* If the width is not passed from the context, then take the
2834 widest result as our width. */
2838 /* If the expression has width, then generate a boolean result
2839 by connecting an OR gate to calculate the truth value of
2840 the result. In the end, the result needs to be a single bit. */
2841 if (expr_sig
->vector_width() > 1) {
2842 NetUReduce
*log
= new NetUReduce(scope
, scope
->local_symbol(),
2844 expr_sig
->vector_width());
2845 log
->set_line(*this);
2847 connect(log
->pin(1), expr_sig
->pin(0));
2849 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2850 NetNet::IMPLICIT
, 1);
2851 tmp
->data_type(IVL_VT_LOGIC
);
2852 tmp
->local_flag(true);
2853 connect(log
->pin(0), tmp
->pin(0));
2858 assert(expr_sig
->vector_width() == 1);
2860 /* This is the width of the LPM_MUX device that I'm about to
2861 create. It may be smaller then the desired output, but I'll
2862 handle padding below. Note that in principle the
2863 alternatives should be padded to the output width first,
2864 but it is more efficient to pad them only just enough to
2865 prevent loss, and do the finished padding later.
2867 Create a NetNet object wide enough to hold the
2868 result. Also, pad the result values (if necessary) so that
2869 the mux inputs can be fully connected. */
2871 unsigned dwidth
= (iwidth
> width
)? width
: iwidth
;
2873 NetNet
*sig
= new NetNet(scope
, scope
->local_symbol(),
2874 NetNet::WIRE
, dwidth
);
2875 sig
->data_type(expr_type
);
2876 sig
->local_flag(true);
2878 if (fal_sig
->vector_width() < dwidth
)
2879 fal_sig
= pad_to_width(des
, fal_sig
, dwidth
);
2881 if (tru_sig
->vector_width() < dwidth
)
2882 tru_sig
= pad_to_width(des
, tru_sig
, dwidth
);
2884 if (dwidth
< fal_sig
->vector_width())
2885 fal_sig
= crop_to_width(des
, fal_sig
, dwidth
);
2887 if (dwidth
< tru_sig
->vector_width())
2888 tru_sig
= crop_to_width(des
, tru_sig
, dwidth
);
2890 /* Make the device and connect its outputs to the osig and
2891 inputs to the tru and false case nets. Also connect the
2892 selector bit to the sel input.
2894 The inputs are the 0 (false) connected to fal_sig and 1
2895 (true) connected to tru_sig. */
2897 NetMux
*mux
= new NetMux(scope
, scope
->local_symbol(), dwidth
, 2, 1);
2898 connect(mux
->pin_Sel(), expr_sig
->pin(0));
2900 /* Connect the data inputs. */
2901 connect(mux
->pin_Data(0), fal_sig
->pin(0));
2902 connect(mux
->pin_Data(1), tru_sig
->pin(0));
2904 /* If there are non-zero output delays, then create bufz
2905 devices to carry the propagation delays. Otherwise, just
2906 connect the result to the output. */
2907 if (rise
|| fall
|| decay
) {
2908 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
2909 NetNet::WIRE
, dwidth
);
2910 tmp
->data_type(expr_type
);
2911 tmp
->local_flag(true);
2913 NetBUFZ
*tmpz
= new NetBUFZ(scope
, scope
->local_symbol(), dwidth
);
2914 tmpz
->rise_time(rise
);
2915 tmpz
->fall_time(fall
);
2916 tmpz
->decay_time(decay
);
2917 tmpz
->pin(0).drive0(drive0
);
2918 tmpz
->pin(0).drive1(drive1
);
2920 connect(mux
->pin_Result(), tmp
->pin(0));
2921 connect(tmp
->pin(0), tmpz
->pin(1));
2922 connect(sig
->pin(0), tmpz
->pin(0));
2924 des
->add_node(tmpz
);
2927 connect(mux
->pin_Result(), sig
->pin(0));
2930 /* If the MUX device result is too narrow to fill out the
2931 desired result, pad with zeros... */
2932 assert(dwidth
<= width
);
2936 /* If the MUX device results is too narrow to fill out the
2937 desired result, then pad it. It is OK to have a too-narrow
2938 result here because the dwidth choice is >= the width of
2939 both alternatives. Thus, padding here is equivalent to
2940 padding inside, and is cheaper. */
2942 sig
= pad_to_width(des
, sig
, width
);
2947 NetNet
* PEUnary::elaborate_net(Design
*des
, NetScope
*scope
,
2949 const NetExpr
* rise
,
2950 const NetExpr
* fall
,
2951 const NetExpr
* decay
,
2952 Link::strength_t drive0
,
2953 Link::strength_t drive1
) const
2956 // Some unary operands allow the operand to be
2957 // self-determined, and some do not.
2958 unsigned owidth
= 0;
2970 // Handle the special case of a 2's complement of a constant
2971 // value. This can be reduced to a no-op on a precalculated
2973 if (op_
== '-') do {
2974 // TODO: Should replace this with a call to
2975 // elab_and_eval. Possibly blend this with the rest of
2976 // the elaboration as well.
2977 verinum
*val
= expr_
->eval_const(des
, scope
);
2985 sig
= new NetNet(scope
, scope
->local_symbol(),
2986 NetNet::WIRE
, width
);
2987 sig
->data_type(IVL_VT_LOGIC
);
2988 sig
->local_flag(true);
2990 /* Take the 2s complement by taking the 1s complement
2992 verinum
tmp (v_not(*val
), width
);
2993 verinum
one (1UL, width
);
2994 tmp
= verinum(tmp
+ one
, width
);
2995 tmp
.has_sign(val
->has_sign());
2997 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(), tmp
);
2998 connect(sig
->pin(0), con
->pin(0));
3000 if (debug_elaborate
) {
3001 cerr
<< get_line() << ": debug: Replace expression "
3002 << *this << " with constant " << tmp
<< "."<<endl
;
3011 NetNet
* sub_sig
= expr_
->elaborate_net(des
, scope
, owidth
, 0, 0, 0);
3018 bool reduction
=false;
3019 NetUReduce::TYPE rtype
= NetUReduce::NONE
;
3022 case '~': // Bitwise NOT
3023 sig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
,
3024 sub_sig
->vector_width());
3025 sig
->data_type(sub_sig
->data_type());
3026 sig
->local_flag(true);
3027 gate
= new NetLogic(scope
, scope
->local_symbol(),
3028 2, NetLogic::NOT
, sub_sig
->vector_width());
3029 gate
->set_line(*this);
3030 des
->add_node(gate
);
3031 gate
->rise_time(rise
);
3032 gate
->fall_time(fall
);
3033 gate
->decay_time(decay
);
3035 connect(gate
->pin(1), sub_sig
->pin(0));
3036 connect(gate
->pin(0), sig
->pin(0));
3039 case 'N': // Reduction NOR
3040 case '!': // Reduction NOT
3041 reduction
=true; rtype
= NetUReduce::NOR
; break;
3042 case '&': // Reduction AND
3043 reduction
=true; rtype
= NetUReduce::AND
; break;
3044 case '|': // Reduction OR
3045 reduction
=true; rtype
= NetUReduce::OR
; break;
3046 case '^': // Reduction XOR
3047 reduction
=true; rtype
= NetUReduce::XOR
; break;
3048 case 'A': // Reduction NAND (~&)
3049 reduction
=true; rtype
= NetUReduce::NAND
; break;
3050 case 'X': // Reduction XNOR (~^)
3051 reduction
=true; rtype
= NetUReduce::XNOR
; break;
3053 case '-': // Unary 2's complement.
3054 // If this expression is self determined, get its width
3055 // from the sub_expression.
3057 owidth
= sub_sig
->vector_width();
3059 sig
= new NetNet(scope
, scope
->local_symbol(),
3060 NetNet::WIRE
, owidth
);
3061 sig
->data_type(sub_sig
->data_type());
3062 sig
->local_flag(true);
3064 if (sub_sig
->vector_width() < owidth
)
3065 sub_sig
= pad_to_width(des
, sub_sig
, owidth
);
3067 switch (sub_sig
->vector_width()) {
3073 gate
= new NetLogic(scope
, scope
->local_symbol(),
3074 2, NetLogic::BUF
, 1);
3075 connect(gate
->pin(0), sig
->pin(0));
3076 connect(gate
->pin(1), sub_sig
->pin(0));
3077 des
->add_node(gate
);
3078 gate
->rise_time(rise
);
3079 gate
->fall_time(fall
);
3080 gate
->decay_time(decay
);
3084 NetAddSub
*sub
= new NetAddSub(scope
, scope
->local_symbol(),
3085 sig
->vector_width());
3086 sub
->attribute(perm_string::literal("LPM_Direction"),
3091 connect(sig
->pin(0), sub
->pin_Result());
3092 connect(sub_sig
->pin(0), sub
->pin_DataB());
3094 verinum
tmp_num (verinum::V0
, sub
->width(), true);
3095 NetConst
*tmp_con
= new NetConst(scope
,
3096 scope
->local_symbol(),
3098 des
->add_node(tmp_con
);
3100 NetNet
*tmp_sig
= new NetNet(scope
, scope
->local_symbol(),
3102 sub_sig
->vector_width());
3103 tmp_sig
->data_type(sub_sig
->data_type());
3104 tmp_sig
->local_flag(true);
3106 connect(tmp_sig
->pin(0), sub
->pin_DataA());
3107 connect(tmp_sig
->pin(0), tmp_con
->pin(0));
3113 cerr
<< "internal error: Unhandled UNARY '" << op_
<< "'" << endl
;
3120 // The output of a reduction operator is 1 bit
3121 sig
= new NetNet(scope
, scope
->local_symbol(), NetNet::WIRE
, 1);
3122 sig
->data_type(sub_sig
->data_type());
3123 sig
->local_flag(true);
3125 rgate
= new NetUReduce(scope
, scope
->local_symbol(),
3126 rtype
, sub_sig
->vector_width());
3127 rgate
->set_line(*this);
3128 connect(rgate
->pin(0), sig
->pin(0));
3129 connect(rgate
->pin(1), sub_sig
->pin(0));
3131 des
->add_node(rgate
);
3132 rgate
->rise_time(rise
);
3133 rgate
->fall_time(fall
);
3134 rgate
->decay_time(decay
);