2 * Copyright (c) 1999-2008 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
21 # include "compiler.h"
27 # include "ivl_assert.h"
29 NetNet
* convert_to_real_const(Design
*des
, NetExpr
*expr
, NetExpr
*obj
)
33 if (NetEConst
*tmp
= dynamic_cast<NetEConst
*>(expr
)) {
34 verireal
vrl(tmp
->value().as_double());
36 sig
= rlval
.synthesize(des
);
38 cerr
<< obj
->get_fileline() << ": sorry: Cannot convert "
39 "bit based value (" << *expr
<< ") to real." << endl
;
47 /* Note that lsig, rsig and real_args are references. */
48 bool process_binary_args(Design
*des
, NetExpr
*left
, NetExpr
*right
,
49 NetNet
*&lsig
, NetNet
*&rsig
, bool&real_args
,
52 if (left
->expr_type() == IVL_VT_REAL
||
53 right
->expr_type() == IVL_VT_REAL
) {
56 /* Currently we will have a runtime assert if both expressions
57 are not real, though we can convert constants. */
58 if (left
->expr_type() == IVL_VT_REAL
) {
59 lsig
= left
->synthesize(des
);
61 lsig
= convert_to_real_const(des
, left
, obj
);
64 if (right
->expr_type() == IVL_VT_REAL
) {
65 rsig
= right
->synthesize(des
);
67 rsig
= convert_to_real_const(des
, right
, obj
);
71 lsig
= left
->synthesize(des
);
72 rsig
= right
->synthesize(des
);
76 if (lsig
== 0 || rsig
== 0) return true;
80 NetNet
* NetExpr::synthesize(Design
*des
)
82 cerr
<< get_fileline() << ": internal error: cannot synthesize expression: "
89 * Make an LPM_ADD_SUB device from addition operators.
91 NetNet
* NetEBAdd::synthesize(Design
*des
)
93 assert((op()=='+') || (op()=='-'));
95 NetNet
*lsig
=0, *rsig
=0;
97 if (process_binary_args(des
, left_
, right_
, lsig
, rsig
,
102 assert(expr_width() >= lsig
->vector_width());
103 assert(expr_width() >= rsig
->vector_width());
105 lsig
= pad_to_width(des
, lsig
, expr_width());
106 rsig
= pad_to_width(des
, rsig
, expr_width());
108 assert(lsig
->vector_width() == rsig
->vector_width());
109 unsigned width
=lsig
->vector_width();
111 perm_string path
= lsig
->scope()->local_symbol();
112 NetNet
*osig
= new NetNet(lsig
->scope(), path
, NetNet::IMPLICIT
, width
);
113 osig
->local_flag(true);
114 osig
->data_type(expr_type());
116 perm_string oname
= osig
->scope()->local_symbol();
117 NetAddSub
*adder
= new NetAddSub(lsig
->scope(), oname
, width
);
118 connect(lsig
->pin(0), adder
->pin_DataA());
119 connect(rsig
->pin(0), adder
->pin_DataB());
120 connect(osig
->pin(0), adder
->pin_Result());
121 des
->add_node(adder
);
125 adder
->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
128 adder
->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
136 * The bitwise logic operators are turned into discrete gates pretty
137 * easily. Synthesize the left and right sub-expressions to get
138 * signals, then just connect a single gate to each bit of the vector
141 NetNet
* NetEBBits::synthesize(Design
*des
)
143 NetNet
*lsig
= left_
->synthesize(des
);
144 NetNet
*rsig
= right_
->synthesize(des
);
146 if (lsig
== 0 || rsig
== 0) return 0;
148 /* You cannot do bitwise operations on real values. */
149 if (lsig
->data_type() == IVL_VT_REAL
||
150 rsig
->data_type() == IVL_VT_REAL
) {
151 cerr
<< get_fileline() << ": error: " << human_readable_op(op_
)
152 << " operator may not have REAL operands." << endl
;
157 NetScope
*scope
= lsig
->scope();
160 unsigned width
= lsig
->vector_width();
161 if (rsig
->vector_width() > width
) width
= rsig
->vector_width();
163 lsig
= pad_to_width(des
, lsig
, width
);
164 rsig
= pad_to_width(des
, rsig
, width
);
166 assert(lsig
->vector_width() == rsig
->vector_width());
167 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
168 NetNet::IMPLICIT
, width
);
169 osig
->local_flag(true);
170 osig
->data_type(expr_type());
172 perm_string oname
= scope
->local_symbol();
177 gate
= new NetLogic(scope
, oname
, 3, NetLogic::AND
, width
);
180 gate
= new NetLogic(scope
, oname
, 3, NetLogic::NAND
, width
);
183 gate
= new NetLogic(scope
, oname
, 3, NetLogic::OR
, width
);
186 gate
= new NetLogic(scope
, oname
, 3, NetLogic::XOR
, width
);
189 gate
= new NetLogic(scope
, oname
, 3, NetLogic::NOR
, width
);
192 gate
= new NetLogic(scope
, oname
, 3, NetLogic::XNOR
, width
);
198 connect(osig
->pin(0), gate
->pin(0));
199 connect(lsig
->pin(0), gate
->pin(1));
200 connect(rsig
->pin(0), gate
->pin(2));
202 gate
->set_line(*this);
208 NetNet
* NetEBComp::synthesize(Design
*des
)
211 NetNet
*lsig
=0, *rsig
=0;
213 bool real_args
=false;
214 if (process_binary_args(des
, left_
, right_
, lsig
, rsig
,
222 width
= lsig
->vector_width();
223 if (rsig
->vector_width() > width
) width
= rsig
->vector_width();
225 lsig
= pad_to_width(des
, lsig
, width
);
226 rsig
= pad_to_width(des
, rsig
, width
);
229 NetScope
*scope
= lsig
->scope();
232 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
233 NetNet::IMPLICIT
, 1);
234 osig
->set_line(*this);
235 osig
->local_flag(true);
236 osig
->data_type(IVL_VT_LOGIC
);
238 bool signed_compare
= lsig
->get_signed() && rsig
->get_signed();
240 /* Handle the special case of a single bit equality
241 operation. Make an XNOR gate instead of a comparator. */
242 if ((width
== 1) && ((op_
== 'e') || (op_
== 'E')) && !real_args
) {
243 NetLogic
*gate
= new NetLogic(scope
, scope
->local_symbol(),
244 3, NetLogic::XNOR
, 1);
245 gate
->set_line(*this);
246 connect(gate
->pin(0), osig
->pin(0));
247 connect(gate
->pin(1), lsig
->pin(0));
248 connect(gate
->pin(2), rsig
->pin(0));
253 /* Handle the special case of a single bit inequality
254 operation. This is similar to single bit equality, but uses
255 an XOR instead of an XNOR gate. */
256 if ((width
== 1) && ((op_
== 'n') || (op_
== 'N')) && !real_args
) {
257 NetLogic
*gate
= new NetLogic(scope
, scope
->local_symbol(),
258 3, NetLogic::XOR
, 1);
259 gate
->set_line(*this);
260 connect(gate
->pin(0), osig
->pin(0));
261 connect(gate
->pin(1), lsig
->pin(0));
262 connect(gate
->pin(2), rsig
->pin(0));
268 NetCompare
*dev
= new NetCompare(scope
, scope
->local_symbol(), width
);
269 dev
->set_line(*this);
272 connect(dev
->pin_DataA(), lsig
->pin(0));
273 connect(dev
->pin_DataB(), rsig
->pin(0));
278 connect(dev
->pin_ALB(), osig
->pin(0));
279 dev
->set_signed(signed_compare
);
282 connect(dev
->pin_AGB(), osig
->pin(0));
283 dev
->set_signed(signed_compare
);
287 cerr
<< get_fileline() << ": error: Case equality may "
288 "not have real operands." << endl
;
293 connect(dev
->pin_AEB(), osig
->pin(0));
296 connect(dev
->pin_AGEB(), osig
->pin(0));
297 dev
->set_signed(signed_compare
);
300 connect(dev
->pin_ALEB(), osig
->pin(0));
301 dev
->set_signed(signed_compare
);
305 cerr
<< get_fileline() << ": error: Case inequality may "
306 "not have real operands." << endl
;
311 connect(dev
->pin_ANEB(), osig
->pin(0));
315 cerr
<< get_fileline() << ": internal error: cannot synthesize "
316 "comparison: " << *this << endl
;
324 NetNet
* NetEBPow::synthesize(Design
*des
)
326 NetNet
*lsig
=0, *rsig
=0;
328 bool real_args
=false;
329 if (process_binary_args(des
, left_
, right_
, lsig
, rsig
,
334 if (real_args
) width
= 1;
335 else width
= expr_width();
337 NetScope
*scope
= lsig
->scope();
340 NetPow
*powr
= new NetPow(scope
, scope
->local_symbol(), width
,
341 lsig
->vector_width(),
342 rsig
->vector_width());
345 powr
->set_signed( has_sign() );
346 powr
->set_line(*this);
348 connect(powr
->pin_DataA(), lsig
->pin(0));
349 connect(powr
->pin_DataB(), rsig
->pin(0));
351 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
352 NetNet::IMPLICIT
, width
);
353 osig
->set_line(*this);
354 osig
->data_type(expr_type());
355 osig
->local_flag(true);
357 connect(powr
->pin_Result(), osig
->pin(0));
362 NetNet
* NetEBMult::synthesize(Design
*des
)
364 NetNet
*lsig
=0, *rsig
=0;
366 bool real_args
=false;
367 if (process_binary_args(des
, left_
, right_
, lsig
, rsig
,
372 if (real_args
) width
= 1;
373 else width
= expr_width();
375 NetScope
*scope
= lsig
->scope();
378 NetMult
*mult
= new NetMult(scope
, scope
->local_symbol(),
380 lsig
->vector_width(),
381 rsig
->vector_width());
384 mult
->set_signed( has_sign() );
385 mult
->set_line(*this);
387 connect(mult
->pin_DataA(), lsig
->pin(0));
388 connect(mult
->pin_DataB(), rsig
->pin(0));
390 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
391 NetNet::IMPLICIT
, width
);
392 osig
->set_line(*this);
393 osig
->data_type(expr_type());
394 osig
->local_flag(true);
396 connect(mult
->pin_Result(), osig
->pin(0));
401 NetNet
* NetEBDiv::synthesize(Design
*des
)
403 NetNet
*lsig
=0, *rsig
=0;
405 bool real_args
=false;
406 if (process_binary_args(des
, left_
, right_
, lsig
, rsig
,
411 if (real_args
) width
= 1;
412 else width
= expr_width();
414 NetScope
*scope
= lsig
->scope();
416 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
417 NetNet::IMPLICIT
, width
);
418 osig
->set_line(*this);
419 osig
->data_type(lsig
->data_type());
420 osig
->local_flag(true);
425 NetDivide
*div
= new NetDivide(scope
, scope
->local_symbol(),
427 lsig
->vector_width(),
428 rsig
->vector_width());
429 div
->set_line(*this);
432 connect(div
->pin_DataA(), lsig
->pin(0));
433 connect(div
->pin_DataB(), rsig
->pin(0));
434 connect(div
->pin_Result(),osig
->pin(0));
439 /* Baseline Verilog does not support the % operator with
440 real arguments, but we allow it in our extended form. */
441 if (real_args
&& !gn_icarus_misc_flag
) {
442 cerr
<< get_fileline() << ": error: Modulus operator "
443 "may not have REAL operands." << endl
;
447 NetModulo
*div
= new NetModulo(scope
, scope
->local_symbol(),
449 lsig
->vector_width(),
450 rsig
->vector_width());
451 div
->set_line(*this);
454 connect(div
->pin_DataA(), lsig
->pin(0));
455 connect(div
->pin_DataB(), rsig
->pin(0));
456 connect(div
->pin_Result(),osig
->pin(0));
461 cerr
<< get_fileline() << ": internal error: "
462 << "NetEBDiv has unexpeced op() code: "
474 NetNet
* NetEBLogic::synthesize(Design
*des
)
476 NetNet
*lsig
= left_
->synthesize(des
);
477 NetNet
*rsig
= right_
->synthesize(des
);
479 if (lsig
== 0 || rsig
== 0) return 0;
481 /* You cannot currently do logical operations on real values. */
482 if (lsig
->data_type() == IVL_VT_REAL
||
483 rsig
->data_type() == IVL_VT_REAL
) {
484 cerr
<< get_fileline() << ": sorry: " << human_readable_op(op_
)
485 << " is currently unsupported for real values." << endl
;
490 NetScope
*scope
= lsig
->scope();
493 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
494 NetNet::IMPLICIT
, 1);
495 osig
->data_type(expr_type());
496 osig
->local_flag(true);
501 /* Logic OR can handle the reduction *and* the logical
502 comparison with a single wide OR gate. So handle this
505 perm_string oname
= scope
->local_symbol();
507 NetLogic
*olog
= new NetLogic(scope
, oname
,
508 lsig
->pin_count()+rsig
->pin_count()+1,
511 connect(osig
->pin(0), olog
->pin(0));
514 for (unsigned idx
= 0 ; idx
< lsig
->pin_count() ; idx
= 1)
515 connect(olog
->pin(pin
+idx
), lsig
->pin(idx
));
517 pin
+= lsig
->pin_count();
518 for (unsigned idx
= 0 ; idx
< rsig
->pin_count() ; idx
= 1)
519 connect(olog
->pin(pin
+idx
), rsig
->pin(idx
));
526 /* Create the logic AND gate. This is a single bit
527 output, with inputs for each of the operands. */
529 perm_string oname
= scope
->local_symbol();
531 olog
= new NetLogic(scope
, oname
, 3, NetLogic::AND
, 1);
533 connect(osig
->pin(0), olog
->pin(0));
536 /* XXXX Here, I need to reduce the parameters with
540 /* By this point, the left and right parameters have been
541 reduced to single bit values. Now we just connect them to
543 assert(lsig
->pin_count() == 1);
544 connect(lsig
->pin(0), olog
->pin(1));
546 assert(rsig
->pin_count() == 1);
547 connect(rsig
->pin(0), olog
->pin(2));
554 NetNet
* NetEBShift::synthesize(Design
*des
)
558 NetNet
*lsig
= left_
->synthesize(des
);
560 if (lsig
== 0) return 0;
562 /* Cannot shift a real values. */
563 if (lsig
->data_type() == IVL_VT_REAL
) {
564 cerr
<< get_fileline() << ": error: shift operator ("
565 << human_readable_op(op_
)
566 << ") cannot shift a real values." << endl
;
571 bool right_flag
= op_
== 'r' || op_
== 'R';
572 bool signed_flag
= op_
== 'R';
574 NetScope
*scope
= lsig
->scope();
576 /* Detect the special case where the shift amount is
577 constant. Evaluate the shift amount, and simply reconnect
578 the left operand to the output, but shifted. */
579 if (NetEConst
*rcon
= dynamic_cast<NetEConst
*>(right_
)) {
580 verinum shift_v
= rcon
->value();
581 long shift
= shift_v
.as_long();
589 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
590 NetNet::IMPLICIT
, expr_width());
591 osig
->data_type(expr_type());
592 osig
->local_flag(true);
594 // ushift is the amount of pad created by the shift.
595 unsigned long ushift
= shift
>=0? shift
: -shift
;
596 if (ushift
> osig
->vector_width())
597 ushift
= osig
->vector_width();
599 // part_width is the bits of the vector that survive the shift.
600 unsigned long part_width
= osig
->vector_width() - ushift
;
602 verinum
znum (verinum::V0
, ushift
, true);
603 NetConst
*zcon
= new NetConst(scope
, scope
->local_symbol(),
607 /* Detect the special case that the shift is the size of
608 the whole expression. Simply connect the pad to the
610 if (ushift
>= osig
->vector_width()) {
611 connect(zcon
->pin(0), osig
->pin(0));
615 NetNet
*zsig
= new NetNet(scope
, scope
->local_symbol(),
616 NetNet::WIRE
, znum
.len());
617 zsig
->data_type(osig
->data_type());
618 zsig
->local_flag(true);
619 zsig
->set_line(*this);
620 connect(zcon
->pin(0), zsig
->pin(0));
622 /* Create a part select to reduce the width of the lsig
623 to the amount left by the shift. */
624 NetPartSelect
*psel
= new NetPartSelect(lsig
, shift
<0? ushift
: 0,
629 NetNet
*psig
= new NetNet(scope
, scope
->local_symbol(),
630 NetNet::IMPLICIT
, part_width
);
631 psig
->data_type(expr_type());
632 psig
->local_flag(true);
633 psig
->set_line(*this);
634 connect(psig
->pin(0), psel
->pin(0));
636 NetConcat
*ccat
= new NetConcat(scope
, scope
->local_symbol(),
637 osig
->vector_width(), 2);
638 ccat
->set_line(*this);
641 connect(ccat
->pin(0), osig
->pin(0));
644 connect(ccat
->pin(1), zsig
->pin(0));
645 connect(ccat
->pin(2), psig
->pin(0));
648 connect(ccat
->pin(1), psig
->pin(0));
649 connect(ccat
->pin(2), zsig
->pin(0));
655 NetNet
*rsig
= right_
->synthesize(des
);
657 if (rsig
== 0) return 0;
659 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
660 NetNet::IMPLICIT
, expr_width());
661 osig
->data_type(expr_type());
662 osig
->local_flag(true);
664 NetCLShift
*dev
= new NetCLShift(scope
, scope
->local_symbol(),
665 osig
->vector_width(),
666 rsig
->vector_width(),
667 right_flag
, signed_flag
);
668 dev
->set_line(*this);
671 connect(dev
->pin_Result(), osig
->pin(0));
673 assert(lsig
->vector_width() == dev
->width());
674 connect(dev
->pin_Data(), lsig
->pin(0));
676 connect(dev
->pin_Distance(), rsig
->pin(0));
681 NetNet
* NetEConcat::synthesize(Design
*des
)
683 /* First, synthesize the operands. */
684 NetNet
**tmp
= new NetNet
*[parms_
.count()];
686 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1) {
687 tmp
[idx
] = parms_
[idx
]->synthesize(des
);
696 NetScope
*scope
= tmp
[0]->scope();
699 /* Make a NetNet object to carry the output vector. */
700 perm_string path
= scope
->local_symbol();
701 NetNet
*osig
= new NetNet(scope
, path
, NetNet::IMPLICIT
, expr_width());
702 osig
->local_flag(true);
703 osig
->data_type(tmp
[0]->data_type());
705 NetConcat
*concat
= new NetConcat(scope
, scope
->local_symbol(),
706 osig
->vector_width(),
707 parms_
.count() * repeat());
708 concat
->set_line(*this);
709 des
->add_node(concat
);
710 connect(concat
->pin(0), osig
->pin(0));
712 unsigned cur_pin
= 1;
713 for (unsigned rpt
= 0; rpt
< repeat(); rpt
+= 1) {
714 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1) {
715 connect(concat
->pin(cur_pin
), tmp
[parms_
.count()-idx
-1]->pin(0));
724 NetNet
* NetEConst::synthesize(Design
*des
)
726 NetScope
*scope
= des
->find_root_scope();
729 perm_string path
= scope
->local_symbol();
730 unsigned width
=expr_width();
732 NetNet
*osig
= new NetNet(scope
, path
, NetNet::IMPLICIT
, width
-1,0);
733 osig
->local_flag(true);
734 osig
->data_type(IVL_VT_LOGIC
);
735 osig
->set_signed(has_sign());
736 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(), value());
737 connect(osig
->pin(0), con
->pin(0));
744 * Create a NetLiteral object to represent real valued constants.
746 NetNet
* NetECReal::synthesize(Design
*des
)
748 NetScope
*scope
= des
->find_root_scope();
751 perm_string path
= scope
->local_symbol();
753 NetNet
*osig
= new NetNet(scope
, path
, NetNet::WIRE
, 1);
754 osig
->local_flag(true);
755 osig
->data_type(IVL_VT_REAL
);
756 osig
->set_signed(has_sign());
757 osig
->set_line(*this);
759 NetLiteral
*con
= new NetLiteral(scope
, scope
->local_symbol(), value_
);
761 con
->set_line(*this);
763 connect(osig
->pin(0), con
->pin(0));
768 * The bitwise unary logic operator (there is only one) is turned
769 * into discrete gates just as easily as the binary ones above.
771 NetNet
* NetEUBits::synthesize(Design
*des
)
773 NetNet
*isig
= expr_
->synthesize(des
);
775 if (isig
== 0) return 0;
777 if (isig
->data_type() == IVL_VT_REAL
) {
778 cerr
<< get_fileline() << ": error: bit-wise negation ("
779 << human_readable_op(op_
)
780 << ") may not have a REAL operand." << endl
;
785 NetScope
*scope
= isig
->scope();
788 unsigned width
= isig
->vector_width();
789 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
790 NetNet::IMPLICIT
, width
);
791 osig
->data_type(expr_type());
792 osig
->local_flag(true);
794 perm_string oname
= scope
->local_symbol();
799 gate
= new NetLogic(scope
, oname
, 2, NetLogic::NOT
, width
);
805 connect(osig
->pin(0), gate
->pin(0));
806 connect(isig
->pin(0), gate
->pin(1));
813 NetNet
* NetEUReduce::synthesize(Design
*des
)
815 NetNet
*isig
= expr_
->synthesize(des
);
817 if (isig
== 0) return 0;
819 if (isig
->data_type() == IVL_VT_REAL
) {
820 cerr
<< get_fileline() << ": error: reduction operator ("
821 << human_readable_op(op_
)
822 << ") may not have a REAL operand." << endl
;
827 NetScope
*scope
= isig
->scope();
830 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
831 NetNet::IMPLICIT
, 1);
832 osig
->data_type(expr_type());
833 osig
->local_flag(true);
835 NetUReduce::TYPE rtype
= NetUReduce::NONE
;
840 rtype
= NetUReduce::NOR
;
843 rtype
= NetUReduce::AND
;
846 rtype
= NetUReduce::OR
;
849 rtype
= NetUReduce::XOR
;
852 rtype
= NetUReduce::XNOR
;
855 rtype
= NetUReduce::XNOR
;
858 cerr
<< get_fileline() << ": internal error: "
859 << "Unable to synthesize " << *this << "." << endl
;
863 NetUReduce
*gate
= new NetUReduce(scope
, scope
->local_symbol(),
864 rtype
, isig
->vector_width());
867 connect(gate
->pin(0), osig
->pin(0));
868 for (unsigned idx
= 0 ; idx
< isig
->pin_count() ; idx
+= 1)
869 connect(gate
->pin(1+idx
), isig
->pin(idx
));
874 NetNet
* NetESelect::synthesize(Design
*des
)
877 NetNet
*sub
= expr_
->synthesize(des
);
879 if (sub
== 0) return 0;
881 NetScope
*scope
= sub
->scope();
885 // This handles the case that the NetESelect exists to do an
886 // actual part/bit select. Generate a NetPartSelect object to
887 // do the work, and replace "sub" with the selected output.
889 off
= base_
->synthesize(des
);
891 NetPartSelect
*sel
= new NetPartSelect(sub
, off
, expr_width());
892 sel
->set_line(*this);
895 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
896 NetNet::IMPLICIT
, expr_width());
897 tmp
->data_type(sub
->data_type());
898 tmp
->local_flag(true);
899 tmp
->set_line(*this);
901 connect(sub
->pin(0), sel
->pin(0));
905 // Now look for the case that the NetESelect actually exists
906 // to change the width of the expression. (i.e. to do
907 // padding.) If this was for an actual part select that at
908 // this point the output vector_width is exactly right, and we
910 if (sub
->vector_width() == expr_width())
913 // The vector_width is not exactly right, so the source is
914 // probably asking for padding. Create nodes to do sign
915 // extension or 0 extension, depending on the has_sign() mode
916 // of the expression.
918 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
919 NetNet::IMPLICIT
, expr_width());
920 net
->data_type(expr_type());
921 net
->local_flag(true);
922 net
->set_line(*this);
924 NetSignExtend
*pad
= new NetSignExtend(scope
,
925 scope
->local_symbol(),
927 pad
->set_line(*this);
930 connect(pad
->pin(1), sub
->pin(0));
931 connect(pad
->pin(0), net
->pin(0));
932 net
->set_signed(true);
936 NetConcat
*cat
= new NetConcat(scope
, scope
->local_symbol(),
938 cat
->set_line(*this);
941 assert(expr_width() > sub
->vector_width());
942 unsigned pad_width
= expr_width() - sub
->vector_width();
943 verinum
pad((uint64_t)0, pad_width
);
944 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(),
946 con
->set_line(*this);
949 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
950 NetNet::IMPLICIT
, pad_width
);
951 tmp
->data_type(expr_type());
952 tmp
->local_flag(true);
953 tmp
->set_line(*this);
954 connect(tmp
->pin(0), con
->pin(0));
956 connect(cat
->pin(0), net
->pin(0));
957 connect(cat
->pin(1), sub
->pin(0));
958 connect(cat
->pin(2), con
->pin(0));
965 * Synthesize a ?: operator as a NetMux device. Connect the condition
966 * expression to the select input, then connect the true and false
967 * expressions to the B and A inputs. This way, when the select input
968 * is one, the B input, which is the true expression, is selected.
970 NetNet
* NetETernary::synthesize(Design
*des
)
972 NetNet
*csig
= cond_
->synthesize(des
),
973 *tsig
= true_val_
->synthesize(des
),
974 *fsig
= false_val_
->synthesize(des
);
976 if (csig
== 0 || tsig
== 0 || fsig
== 0) return 0;
978 if (tsig
->data_type() != fsig
->data_type()) {
979 cerr
<< get_fileline() << ": error: True and False clauses of "
980 "ternary expression have different types." << endl
;
981 cerr
<< get_fileline() << ": : True clause is: "
982 << tsig
->data_type() << endl
;
983 cerr
<< get_fileline() << ": : False clause is: "
984 << fsig
->data_type() << endl
;
987 } else if (tsig
->data_type() == IVL_VT_NO_TYPE
) {
988 cerr
<< get_fileline() << ": internal error: True and False "
989 "clauses of ternary both have NO TYPE." << endl
;
994 perm_string path
= csig
->scope()->local_symbol();
996 assert(csig
->vector_width() == 1);
998 unsigned width
=expr_width();
999 NetNet
*osig
= new NetNet(csig
->scope(), path
, NetNet::IMPLICIT
, width
);
1000 osig
->data_type(expr_type());
1001 osig
->local_flag(true);
1003 /* Make sure both value operands are the right width. */
1004 tsig
= crop_to_width(des
, pad_to_width(des
, tsig
, width
), width
);
1005 fsig
= crop_to_width(des
, pad_to_width(des
, fsig
, width
), width
);
1007 assert(width
== tsig
->vector_width());
1008 assert(width
== fsig
->vector_width());
1010 perm_string oname
= csig
->scope()->local_symbol();
1011 NetMux
*mux
= new NetMux(csig
->scope(), oname
, width
,
1012 2, csig
->vector_width());
1013 connect(tsig
->pin(0), mux
->pin_Data(1));
1014 connect(fsig
->pin(0), mux
->pin_Data(0));
1015 connect(osig
->pin(0), mux
->pin_Result());
1016 connect(csig
->pin(0), mux
->pin_Sel());
1023 * When synthesizing a signal expression, it is usually fine to simply
1024 * return the NetNet that it refers to. If this is an array word though,
1025 * a bit more work needs to be done. Return a temporary that represents
1026 * the selected word.
1028 NetNet
* NetESignal::synthesize(Design
*des
)
1033 NetScope
*scope
= net_
->scope();
1035 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
1036 NetNet::IMPLICIT
, net_
->vector_width());
1037 tmp
->set_line(*this);
1038 tmp
->local_flag(true);
1039 tmp
->data_type(net_
->data_type());
1041 if (NetEConst
*index_co
= dynamic_cast<NetEConst
*> (word_
)) {
1042 long index
= index_co
->value().as_long();
1044 assert(net_
->array_index_is_valid(index
));
1045 index
= net_
->array_index_to_address(index
);
1047 connect(tmp
->pin(0), net_
->pin(index
));
1049 unsigned selwid
= word_
->expr_width();
1051 NetArrayDq
*mux
= new NetArrayDq(scope
, scope
->local_symbol(),
1053 mux
->set_line(*this);
1056 NetNet
*index_net
= word_
->synthesize(des
);
1057 connect(mux
->pin_Address(), index_net
->pin(0));
1059 connect(tmp
->pin(0), mux
->pin_Result());
1064 NetNet
* NetESFunc::synthesize(Design
*des
)
1066 cerr
<< get_fileline() << ": sorry: cannot synthesize system function: "
1067 << *this << " in this context" << endl
;
1072 NetNet
* NetEUFunc::synthesize(Design
*des
)
1074 svector
<NetNet
*> eparms (parms_
.count());
1076 /* Synthesize the arguments. */
1077 bool errors
= false;
1078 for (unsigned idx
= 0; idx
< eparms
.count(); idx
+= 1) {
1079 NetNet
*tmp
= parms_
[idx
]->synthesize(des
);
1081 cerr
<< get_fileline() << ": error: Unable to synthesize "
1082 "port " << idx
<< " of call to "
1083 << func_
->basename() << "." << endl
;
1090 if (errors
) return 0;
1092 NetUserFunc
*net
= new NetUserFunc(scope_
, scope_
->local_symbol(), func_
);
1093 net
->set_line(*this);
1096 /* Create an output signal and connect it to the function. */
1097 NetNet
*osig
= new NetNet(scope_
, scope_
->local_symbol(), NetNet::WIRE
,
1098 result_sig_
->vector_width());
1099 osig
->local_flag(true);
1100 osig
->data_type(result_sig_
->expr_type());
1101 connect(net
->pin(0), osig
->pin(0));
1103 /* Connect the pins to the arguments. */
1104 NetFuncDef
*def
= func_
->func_def();
1105 for (unsigned idx
= 0; idx
< eparms
.count(); idx
+= 1) {
1106 NetNet
*tmp
= pad_to_width(des
, eparms
[idx
],
1107 def
->port(idx
)->vector_width());
1108 connect(net
->pin(idx
+1), tmp
->pin(0));