2 * Copyright (c) 1999-2005 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: expr_synth.cc,v 1.87 2007/06/02 03:42:12 steve Exp $"
29 # include "ivl_assert.h"
31 NetNet
* NetExpr::synthesize(Design
*des
)
33 cerr
<< get_line() << ": internal error: cannot synthesize expression: "
40 * Make an LPM_ADD_SUB device from addition operators.
42 NetNet
* NetEBAdd::synthesize(Design
*des
)
44 assert((op()=='+') || (op()=='-'));
46 NetNet
*lsig
= left_
->synthesize(des
);
47 NetNet
*rsig
= right_
->synthesize(des
);
49 assert(expr_width() >= lsig
->vector_width());
50 assert(expr_width() >= rsig
->vector_width());
52 lsig
= pad_to_width(des
, lsig
, expr_width());
53 rsig
= pad_to_width(des
, rsig
, expr_width());
55 assert(lsig
->vector_width() == rsig
->vector_width());
56 unsigned width
=lsig
->vector_width();
58 perm_string path
= lsig
->scope()->local_symbol();
59 NetNet
*osig
= new NetNet(lsig
->scope(), path
, NetNet::IMPLICIT
, width
);
60 osig
->local_flag(true);
61 osig
->data_type(expr_type());
63 perm_string oname
= osig
->scope()->local_symbol();
64 NetAddSub
*adder
= new NetAddSub(lsig
->scope(), oname
, width
);
65 connect(lsig
->pin(0), adder
->pin_DataA());
66 connect(rsig
->pin(0), adder
->pin_DataB());
67 connect(osig
->pin(0), adder
->pin_Result());
72 adder
->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
75 adder
->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
83 * The bitwise logic operators are turned into discrete gates pretty
84 * easily. Synthesize the left and right sub-expressions to get
85 * signals, then just connect a single gate to each bit of the vector
88 NetNet
* NetEBBits::synthesize(Design
*des
)
90 NetNet
*lsig
= left_
->synthesize(des
);
91 NetNet
*rsig
= right_
->synthesize(des
);
93 NetScope
*scope
= lsig
->scope();
96 if (lsig
->vector_width() != rsig
->vector_width()) {
97 cerr
<< get_line() << ": internal error: bitwise (" << op_
98 << ") widths do not match: " << lsig
->vector_width()
99 << " != " << rsig
->vector_width() << endl
;
100 cerr
<< get_line() << ": : width="
101 << lsig
->vector_width() << ": " << *left_
<< endl
;
102 cerr
<< get_line() << ": : width="
103 << rsig
->vector_width() << ": " << *right_
<< endl
;
107 assert(lsig
->vector_width() == rsig
->vector_width());
108 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
109 NetNet::IMPLICIT
, lsig
->vector_width());
110 osig
->local_flag(true);
111 osig
->data_type(expr_type());
113 perm_string oname
= scope
->local_symbol();
114 unsigned wid
= lsig
->vector_width();
119 gate
= new NetLogic(scope
, oname
, 3, NetLogic::AND
, wid
);
122 gate
= new NetLogic(scope
, oname
, 3, NetLogic::OR
, wid
);
125 gate
= new NetLogic(scope
, oname
, 3, NetLogic::XOR
, wid
);
128 gate
= new NetLogic(scope
, oname
, 3, NetLogic::NOR
, wid
);
131 gate
= new NetLogic(scope
, oname
, 3, NetLogic::XNOR
, wid
);
137 connect(osig
->pin(0), gate
->pin(0));
138 connect(lsig
->pin(0), gate
->pin(1));
139 connect(rsig
->pin(0), gate
->pin(2));
141 gate
->set_line(*this);
147 NetNet
* NetEBComp::synthesize(Design
*des
)
150 NetNet
*lsig
= left_
->synthesize(des
);
151 NetNet
*rsig
= right_
->synthesize(des
);
153 NetScope
*scope
= lsig
->scope();
156 unsigned width
= lsig
->vector_width();
157 if (rsig
->vector_width() > width
)
158 width
= rsig
->vector_width();
160 lsig
= pad_to_width(des
, lsig
, width
);
161 rsig
= pad_to_width(des
, rsig
, width
);
163 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
164 NetNet::IMPLICIT
, 1);
165 osig
->set_line(*this);
166 osig
->local_flag(true);
167 osig
->data_type(IVL_VT_LOGIC
);
169 /* Handle the special case of a single bit equality
170 operation. Make an XNOR gate instead of a comparator. */
171 if ((width
== 1) && ((op_
== 'e') || (op_
== 'E'))) {
172 NetLogic
*gate
= new NetLogic(scope
, scope
->local_symbol(),
173 3, NetLogic::XNOR
, 1);
174 gate
->set_line(*this);
175 connect(gate
->pin(0), osig
->pin(0));
176 connect(gate
->pin(1), lsig
->pin(0));
177 connect(gate
->pin(2), rsig
->pin(0));
182 /* Handle the special case of a single bit inequality
183 operation. This is similar to single bit equality, but uses
184 an XOR instead of an XNOR gate. */
185 if ((width
== 1) && ((op_
== 'n') || (op_
== 'N'))) {
186 NetLogic
*gate
= new NetLogic(scope
, scope
->local_symbol(),
187 3, NetLogic::XOR
, 1);
188 gate
->set_line(*this);
189 connect(gate
->pin(0), osig
->pin(0));
190 connect(gate
->pin(1), lsig
->pin(0));
191 connect(gate
->pin(2), rsig
->pin(0));
197 NetCompare
*dev
= new NetCompare(scope
, scope
->local_symbol(), width
);
198 dev
->set_line(*this);
201 connect(dev
->pin_DataA(), lsig
->pin(0));
202 connect(dev
->pin_DataB(), rsig
->pin(0));
207 connect(dev
->pin_ALB(), osig
->pin(0));
210 connect(dev
->pin_AGB(), osig
->pin(0));
214 connect(dev
->pin_AEB(), osig
->pin(0));
217 connect(dev
->pin_AGEB(), osig
->pin(0));
220 connect(dev
->pin_ALEB(), osig
->pin(0));
224 connect(dev
->pin_ANEB(), osig
->pin(0));
228 cerr
<< get_line() << ": internal error: cannot synthesize "
229 "comparison: " << *this << endl
;
237 NetNet
* NetEBPow::synthesize(Design
*des
)
239 cerr
<< get_line() << ": internal error: Do not yet know how to handle"
240 << " power operator in this context." << endl
;
245 NetNet
* NetEBMult::synthesize(Design
*des
)
247 NetNet
*lsig
= left_
->synthesize(des
);
248 NetNet
*rsig
= right_
->synthesize(des
);
256 NetScope
*scope
= lsig
->scope();
259 NetMult
*mult
= new NetMult(scope
, scope
->local_symbol(),
261 lsig
->vector_width(),
262 rsig
->vector_width());
265 mult
->set_signed( has_sign() );
266 mult
->set_line(*this);
268 connect(mult
->pin_DataA(), lsig
->pin(0));
269 connect(mult
->pin_DataB(), rsig
->pin(0));
271 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
272 NetNet::IMPLICIT
, expr_width());
273 osig
->data_type(lsig
->data_type());
274 osig
->set_line(*this);
275 osig
->data_type(expr_type());
276 osig
->local_flag(true);
278 connect(mult
->pin_Result(), osig
->pin(0));
283 NetNet
* NetEBDiv::synthesize(Design
*des
)
285 NetNet
*lsig
= left_
->synthesize(des
);
286 NetNet
*rsig
= right_
->synthesize(des
);
288 NetScope
*scope
= lsig
->scope();
290 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
291 NetNet::IMPLICIT
, expr_width());
292 osig
->set_line(*this);
293 osig
->data_type(lsig
->data_type());
294 osig
->local_flag(true);
299 NetDivide
*div
= new NetDivide(scope
, scope
->local_symbol(),
301 lsig
->vector_width(),
302 rsig
->vector_width());
303 div
->set_line(*this);
306 connect(div
->pin_DataA(), lsig
->pin(0));
307 connect(div
->pin_DataB(), rsig
->pin(0));
308 connect(div
->pin_Result(),osig
->pin(0));
313 NetModulo
*div
= new NetModulo(scope
, scope
->local_symbol(),
315 lsig
->vector_width(),
316 rsig
->vector_width());
317 div
->set_line(*this);
320 connect(div
->pin_DataA(), lsig
->pin(0));
321 connect(div
->pin_DataB(), rsig
->pin(0));
322 connect(div
->pin_Result(),osig
->pin(0));
327 cerr
<< get_line() << ": internal error: "
328 << "NetEBDiv has unexpeced op() code: "
340 NetNet
* NetEBLogic::synthesize(Design
*des
)
342 NetNet
*lsig
= left_
->synthesize(des
);
343 NetNet
*rsig
= right_
->synthesize(des
);
351 NetScope
*scope
= lsig
->scope();
354 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
355 NetNet::IMPLICIT
, 1);
356 osig
->data_type(expr_type());
357 osig
->local_flag(true);
362 /* Logic OR can handle the reduction *and* the logical
363 comparison with a single wide OR gate. So handle this
366 perm_string oname
= scope
->local_symbol();
368 NetLogic
*olog
= new NetLogic(scope
, oname
,
369 lsig
->pin_count()+rsig
->pin_count()+1,
372 connect(osig
->pin(0), olog
->pin(0));
375 for (unsigned idx
= 0 ; idx
< lsig
->pin_count() ; idx
= 1)
376 connect(olog
->pin(pin
+idx
), lsig
->pin(idx
));
378 pin
+= lsig
->pin_count();
379 for (unsigned idx
= 0 ; idx
< rsig
->pin_count() ; idx
= 1)
380 connect(olog
->pin(pin
+idx
), rsig
->pin(idx
));
387 /* Create the logic AND gate. This is a single bit
388 output, with inputs for each of the operands. */
390 perm_string oname
= scope
->local_symbol();
392 olog
= new NetLogic(scope
, oname
, 3, NetLogic::AND
, 1);
394 connect(osig
->pin(0), olog
->pin(0));
397 /* XXXX Here, I need to reduce the parameters with
401 /* By this point, the left and right parameters have been
402 reduced to single bit values. Now we just connect them to
404 assert(lsig
->pin_count() == 1);
405 connect(lsig
->pin(0), olog
->pin(1));
407 assert(rsig
->pin_count() == 1);
408 connect(rsig
->pin(0), olog
->pin(2));
415 NetNet
* NetEBShift::synthesize(Design
*des
)
417 if (! dynamic_cast<NetEConst
*>(right_
)) {
418 NetExpr
*tmp
= right_
->eval_tree();
425 NetNet
*lsig
= left_
->synthesize(des
);
429 bool right_flag
= op_
== 'r' || op_
== 'R';
430 bool signed_flag
= op_
== 'R';
432 NetScope
*scope
= lsig
->scope();
434 /* Detect the special case where the shift amount is
435 constant. Evaluate the shift amount, and simply reconnect
436 the left operand to the output, but shifted. */
437 if (NetEConst
*rcon
= dynamic_cast<NetEConst
*>(right_
)) {
438 verinum shift_v
= rcon
->value();
439 long shift
= shift_v
.as_long();
447 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
448 NetNet::IMPLICIT
, expr_width());
449 osig
->data_type(expr_type());
450 osig
->local_flag(true);
452 // ushift is the amount of pad created by the shift.
453 unsigned long ushift
= shift
>=0? shift
: -shift
;
454 if (ushift
> osig
->vector_width())
455 ushift
= osig
->vector_width();
457 // part_width is the bits of the vector that survive the shift.
458 unsigned long part_width
= osig
->vector_width() - ushift
;
460 verinum
znum (verinum::V0
, ushift
, true);
461 NetConst
*zcon
= new NetConst(scope
, scope
->local_symbol(),
465 /* Detect the special case that the shift is the size of
466 the whole expression. Simply connect the pad to the
468 if (ushift
>= osig
->vector_width()) {
469 connect(zcon
->pin(0), osig
->pin(0));
473 NetNet
*zsig
= new NetNet(scope
, scope
->local_symbol(),
474 NetNet::WIRE
, znum
.len());
475 zsig
->data_type(osig
->data_type());
476 zsig
->local_flag(true);
477 zsig
->set_line(*this);
478 connect(zcon
->pin(0), zsig
->pin(0));
480 /* Create a part select to reduce the width of the lsig
481 to the amount left by the shift. */
482 NetPartSelect
*psel
= new NetPartSelect(lsig
, shift
<0? ushift
: 0,
487 NetNet
*psig
= new NetNet(scope
, scope
->local_symbol(),
488 NetNet::IMPLICIT
, part_width
);
489 psig
->data_type(expr_type());
490 psig
->local_flag(true);
491 psig
->set_line(*this);
492 connect(psig
->pin(0), psel
->pin(0));
494 NetConcat
*ccat
= new NetConcat(scope
, scope
->local_symbol(),
495 osig
->vector_width(), 2);
496 ccat
->set_line(*this);
499 connect(ccat
->pin(0), osig
->pin(0));
502 connect(ccat
->pin(1), zsig
->pin(0));
503 connect(ccat
->pin(2), psig
->pin(0));
506 connect(ccat
->pin(1), psig
->pin(0));
507 connect(ccat
->pin(2), zsig
->pin(0));
513 NetNet
*rsig
= right_
->synthesize(des
);
517 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
518 NetNet::IMPLICIT
, expr_width());
519 osig
->data_type(expr_type());
520 osig
->local_flag(true);
522 NetCLShift
*dev
= new NetCLShift(scope
, scope
->local_symbol(),
523 osig
->vector_width(),
524 rsig
->vector_width(),
525 right_flag
, signed_flag
);
526 dev
->set_line(*this);
529 connect(dev
->pin_Result(), osig
->pin(0));
531 assert(lsig
->vector_width() == dev
->width());
532 connect(dev
->pin_Data(), lsig
->pin(0));
534 connect(dev
->pin_Distance(), rsig
->pin(0));
539 NetNet
* NetEConcat::synthesize(Design
*des
)
541 /* First, synthesize the operands. */
542 NetNet
**tmp
= new NetNet
*[parms_
.count()];
544 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1) {
545 tmp
[idx
] = parms_
[idx
]->synthesize(des
);
554 NetScope
*scope
= tmp
[0]->scope();
557 /* Make a NetNet object to carry the output vector. */
558 perm_string path
= scope
->local_symbol();
559 NetNet
*osig
= new NetNet(scope
, path
, NetNet::IMPLICIT
, expr_width());
560 osig
->local_flag(true);
561 osig
->data_type(tmp
[0]->data_type());
563 NetConcat
*concat
= new NetConcat(scope
, scope
->local_symbol(),
564 osig
->vector_width(), parms_
.count());
565 concat
->set_line(*this);
566 des
->add_node(concat
);
567 connect(concat
->pin(0), osig
->pin(0));
569 for (unsigned idx
= 0 ; idx
< parms_
.count() ; idx
+= 1) {
570 connect(concat
->pin(idx
+1), tmp
[parms_
.count()-idx
-1]->pin(0));
577 NetNet
* NetEConst::synthesize(Design
*des
)
579 NetScope
*scope
= des
->find_root_scope();
582 perm_string path
= scope
->local_symbol();
583 unsigned width
=expr_width();
585 NetNet
*osig
= new NetNet(scope
, path
, NetNet::IMPLICIT
, width
-1,0);
586 osig
->local_flag(true);
587 osig
->data_type(IVL_VT_LOGIC
);
588 osig
->set_signed(has_sign());
589 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(), value());
590 connect(osig
->pin(0), con
->pin(0));
597 * Create a NetLiteral object to represent real valued constants.
599 NetNet
* NetECReal::synthesize(Design
*des
)
601 NetScope
*scope
= des
->find_root_scope();
604 perm_string path
= scope
->local_symbol();
606 NetNet
*osig
= new NetNet(scope
, path
, NetNet::WIRE
, 1);
607 osig
->local_flag(true);
608 osig
->data_type(IVL_VT_REAL
);
609 osig
->set_signed(has_sign());
610 osig
->set_line(*this);
612 NetLiteral
*con
= new NetLiteral(scope
, scope
->local_symbol(), value_
);
614 con
->set_line(*this);
616 connect(osig
->pin(0), con
->pin(0));
621 * The bitwise unary logic operator (there is only one) is turned
622 * into discrete gates just as easily as the binary ones above.
624 NetNet
* NetEUBits::synthesize(Design
*des
)
626 NetNet
*isig
= expr_
->synthesize(des
);
628 NetScope
*scope
= isig
->scope();
631 unsigned width
= isig
->vector_width();
632 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
633 NetNet::IMPLICIT
, width
);
634 osig
->data_type(expr_type());
635 osig
->local_flag(true);
637 perm_string oname
= scope
->local_symbol();
642 gate
= new NetLogic(scope
, oname
, 2, NetLogic::NOT
, width
);
648 connect(osig
->pin(0), gate
->pin(0));
649 connect(isig
->pin(0), gate
->pin(1));
656 NetNet
* NetEUReduce::synthesize(Design
*des
)
658 NetNet
*isig
= expr_
->synthesize(des
);
660 NetScope
*scope
= isig
->scope();
663 NetNet
*osig
= new NetNet(scope
, scope
->local_symbol(),
664 NetNet::IMPLICIT
, 1);
665 osig
->data_type(expr_type());
666 osig
->local_flag(true);
668 NetUReduce::TYPE rtype
= NetUReduce::NONE
;
673 rtype
= NetUReduce::NOR
;
676 rtype
= NetUReduce::AND
;
679 rtype
= NetUReduce::OR
;
682 rtype
= NetUReduce::XOR
;
685 rtype
= NetUReduce::XNOR
;
688 rtype
= NetUReduce::XNOR
;
691 cerr
<< get_line() << ": internal error: "
692 << "Unable to synthesize " << *this << "." << endl
;
696 NetUReduce
*gate
= new NetUReduce(scope
, scope
->local_symbol(),
697 rtype
, isig
->vector_width());
700 connect(gate
->pin(0), osig
->pin(0));
701 for (unsigned idx
= 0 ; idx
< isig
->pin_count() ; idx
+= 1)
702 connect(gate
->pin(1+idx
), isig
->pin(idx
));
707 NetNet
* NetESelect::synthesize(Design
*des
)
710 NetNet
*sub
= expr_
->synthesize(des
);
714 NetScope
*scope
= sub
->scope();
718 // This handles the case that the NetESelect exists to do an
719 // actual part/bit select. Generate a NetPartSelect object to
720 // do the work, and replace "sub" with the selected output.
722 off
= base_
->synthesize(des
);
724 NetPartSelect
*sel
= new NetPartSelect(sub
, off
, expr_width());
725 sel
->set_line(*this);
728 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
729 NetNet::IMPLICIT
, expr_width());
730 tmp
->data_type(sub
->data_type());
731 tmp
->local_flag(true);
732 tmp
->set_line(*this);
734 connect(sub
->pin(0), sel
->pin(0));
738 // Now look for the case that the NetESelect actually exists
739 // to change the width of the expression. (i.e. to do
740 // padding.) If this was for an actual part select that at
741 // this point the output vector_width is exactly right, and we
743 if (sub
->vector_width() == expr_width())
746 // The vector_width is not exactly right, so the source is
747 // probably asking for padding. Create nodes to do sign
748 // extension or 0 extension, depending on the has_sign() mode
749 // of the expression.
751 NetNet
*net
= new NetNet(scope
, scope
->local_symbol(),
752 NetNet::IMPLICIT
, expr_width());
753 net
->data_type(expr_type());
754 net
->local_flag(true);
755 net
->set_line(*this);
757 NetSignExtend
*pad
= new NetSignExtend(scope
,
758 scope
->local_symbol(),
760 pad
->set_line(*this);
763 connect(pad
->pin(1), sub
->pin(0));
764 connect(pad
->pin(0), net
->pin(0));
768 NetConcat
*cat
= new NetConcat(scope
, scope
->local_symbol(),
770 cat
->set_line(*this);
773 assert(expr_width() > sub
->vector_width());
774 unsigned pad_width
= expr_width() - sub
->vector_width();
775 verinum
pad((uint64_t)0, pad_width
);
776 NetConst
*con
= new NetConst(scope
, scope
->local_symbol(),
778 con
->set_line(*this);
781 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
782 NetNet::IMPLICIT
, pad_width
);
783 tmp
->data_type(expr_type());
784 tmp
->local_flag(true);
785 tmp
->set_line(*this);
786 connect(tmp
->pin(0), con
->pin(0));
788 connect(cat
->pin(0), net
->pin(0));
789 connect(cat
->pin(1), sub
->pin(0));
790 connect(cat
->pin(2), con
->pin(0));
797 * Synthesize a ?: operator as a NetMux device. Connect the condition
798 * expression to the select input, then connect the true and false
799 * expressions to the B and A inputs. This way, when the select input
800 * is one, the B input, which is the true expression, is selected.
802 NetNet
* NetETernary::synthesize(Design
*des
)
804 NetNet
*csig
= cond_
->synthesize(des
);
805 NetNet
*tsig
= true_val_
->synthesize(des
);
806 NetNet
*fsig
= false_val_
->synthesize(des
);
808 perm_string path
= csig
->scope()->local_symbol();
810 assert(csig
->vector_width() == 1);
812 unsigned width
=expr_width();
813 NetNet
*osig
= new NetNet(csig
->scope(), path
, NetNet::IMPLICIT
, width
);
814 osig
->data_type(expr_type());
815 osig
->local_flag(true);
817 /* Make sure both value operands are the right width. */
818 tsig
= crop_to_width(des
, pad_to_width(des
, tsig
, width
), width
);
819 fsig
= crop_to_width(des
, pad_to_width(des
, fsig
, width
), width
);
821 assert(width
== tsig
->vector_width());
822 assert(width
== fsig
->vector_width());
824 perm_string oname
= csig
->scope()->local_symbol();
825 NetMux
*mux
= new NetMux(csig
->scope(), oname
, width
,
826 2, csig
->vector_width());
827 connect(tsig
->pin(0), mux
->pin_Data(1));
828 connect(fsig
->pin(0), mux
->pin_Data(0));
829 connect(osig
->pin(0), mux
->pin_Result());
830 connect(csig
->pin(0), mux
->pin_Sel());
837 * When synthesizing a signal expression, it is usually fine to simply
838 * return the NetNet that it refers to. If this is a part select,
839 * though, a bit more work needs to be done. Return a temporary that
840 * represents the connections to the selected bits.
842 * For example, if there is a reg foo, like so:
844 * and this expression node represents a part select foo[3:2], then
845 * create a temporary like so:
861 * The temporary is marked as a temporary and returned to the
862 * caller. This causes the caller to get only the selected part of the
863 * signal, and when it hooks up to tmp, it hooks up to the right parts
866 NetNet
* NetESignal::synthesize(Design
*des
)
872 * $Log: expr_synth.cc,v $
873 * Revision 1.87 2007/06/02 03:42:12 steve
874 * Properly evaluate scope path expressions.
876 * Revision 1.86 2007/04/15 01:37:29 steve
877 * Allow bit/part select of vectors in continuous assignments.
879 * Revision 1.85 2007/04/12 05:21:54 steve
880 * fix handling of unary reduction logic in certain nets.
882 * Revision 1.84 2007/04/04 02:31:57 steve
883 * Remove useless assert
885 * Revision 1.83 2007/02/05 01:42:31 steve
886 * Set some missing local flags.
888 * Revision 1.82 2007/01/20 02:10:45 steve
889 * Get argument widths right for shift results.
891 * Revision 1.81 2007/01/16 05:44:15 steve
892 * Major rework of array handling. Memories are replaced with the
893 * more general concept of arrays. The NetMemory and NetEMemory
894 * classes are removed from the ivl core program, and the IVL_LPM_RAM
895 * lpm type is removed from the ivl_target API.
897 * Revision 1.80 2006/08/08 05:11:37 steve
898 * Handle 64bit delay constants.
900 * Revision 1.79 2006/07/31 03:50:17 steve
901 * Add support for power in constant expressions.
903 * Revision 1.78 2006/07/08 21:48:46 steve
904 * Handle real valued literals in net contexts.
906 * Revision 1.77 2006/05/01 20:47:59 steve
907 * More explicit datatype setup.
909 * Revision 1.76 2006/05/01 05:40:21 steve
910 * fix net type of multiply output.
912 * Revision 1.75 2006/04/30 05:17:48 steve
913 * Get the data type of part select results right.
915 * Revision 1.74 2006/01/03 05:15:33 steve
916 * Fix the return type of a synthesized divide.
918 * Revision 1.73 2005/09/15 23:04:09 steve
919 * Make sure div, mod and mult nodes have line number info.
921 * Revision 1.72 2005/08/31 05:07:31 steve
922 * Handle memory references is continuous assignments.
924 * Revision 1.71 2005/06/13 23:22:14 steve
925 * use NetPartSelect to shrink part from high bits.
927 * Revision 1.70 2005/06/13 22:26:03 steve
928 * Make synthesized padding vector-aware.
930 * Revision 1.69 2005/05/15 04:47:00 steve
931 * synthesis of Logic and shifts using vector gates.
933 * Revision 1.68 2005/05/06 00:25:13 steve
934 * Handle synthesis of concatenation expressions.
936 * Revision 1.67 2005/04/25 01:30:31 steve
937 * synthesis of add and unary get vector widths right.
939 * Revision 1.66 2005/04/24 23:44:02 steve
940 * Update DFF support to new data flow.
942 * Revision 1.65 2005/03/12 06:43:35 steve
943 * Update support for LPM_MOD.
945 * Revision 1.64 2005/02/19 02:43:38 steve
946 * Support shifts and divide.
948 * Revision 1.63 2005/02/12 06:25:40 steve
949 * Restructure NetMux devices to pass vectors.
950 * Generate NetMux devices from ternary expressions,
951 * Reduce NetMux devices to bufif when appropriate.
953 * Revision 1.62 2005/01/28 05:39:33 steve
954 * Simplified NetMult and IVL_LPM_MULT.
956 * Revision 1.61 2005/01/16 04:20:32 steve
957 * Implement LPM_COMPARE nodes as two-input vector functors.
959 * Revision 1.60 2004/12/11 02:31:26 steve
960 * Rework of internals to carry vectors through nexus instead
961 * of single bits. Make the ivl, tgt-vvp and vvp initial changes
964 * Revision 1.59 2004/06/30 02:16:26 steve
965 * Implement signed divide and signed right shift in nets.
967 * Revision 1.58 2004/06/16 16:21:34 steve
968 * Connect rsif of multiply to DataB.
970 * Revision 1.57 2004/06/12 15:00:02 steve
971 * Support / and % in synthesized contexts.
973 * Revision 1.56 2004/06/01 01:04:57 steve
974 * Fix synthesis method for logical and/or
976 * Revision 1.55 2004/02/20 18:53:35 steve
977 * Addtrbute keys are perm_strings.
979 * Revision 1.54 2004/02/18 17:11:56 steve
980 * Use perm_strings for named langiage items.
982 * Revision 1.53 2004/02/15 04:23:48 steve
983 * Fix evaluation of compare to constant expression.
985 * Revision 1.52 2003/11/10 19:39:20 steve
986 * Remove redundant scope tokens.
988 * Revision 1.51 2003/10/27 06:04:21 steve
989 * More flexible width handling for synthesized add.
991 * Revision 1.50 2003/09/26 02:44:27 steve
992 * Assure ternary arguments are wide enough.
994 * Revision 1.49 2003/09/03 23:31:36 steve
995 * Support synthesis of constant downshifts.
997 * Revision 1.48 2003/08/28 04:11:18 steve
1000 * Revision 1.47 2003/08/09 03:23:40 steve
1001 * Add support for IVL_LPM_MULT device.
1003 * Revision 1.46 2003/07/26 03:34:42 steve
1004 * Start handling pad of expressions in code generators.
1006 * Revision 1.45 2003/06/24 01:38:02 steve
1007 * Various warnings fixed.
1009 * Revision 1.44 2003/04/19 04:52:56 steve
1010 * Less picky about expression widths while synthesizing ternary.
1012 * Revision 1.43 2003/04/08 05:07:15 steve
1013 * Detect constant shift distances in synthesis.
1015 * Revision 1.42 2003/04/08 04:33:55 steve
1016 * Synthesize shift expressions.
1018 * Revision 1.41 2003/03/06 00:28:41 steve
1019 * All NetObj objects have lex_string base names.
1021 * Revision 1.40 2003/02/26 01:29:24 steve
1022 * LPM objects store only their base names.
1024 * Revision 1.39 2003/01/30 16:23:07 steve
1027 * Revision 1.38 2003/01/26 21:15:58 steve
1028 * Rework expression parsing and elaboration to
1029 * accommodate real/realtime values and expressions.
1031 * Revision 1.37 2002/11/17 23:37:55 steve
1032 * Magnitude compare to 0.
1034 * Revision 1.36 2002/08/12 01:34:59 steve
1035 * conditional ident string using autoconfig.
1037 * Revision 1.35 2002/07/07 22:31:39 steve
1038 * Smart synthesis of binary AND expressions.
1040 * Revision 1.34 2002/07/05 21:26:17 steve
1041 * Avoid emitting to vvp local net symbols.
1043 * Revision 1.33 2002/05/26 01:39:02 steve
1044 * Carry Verilog 2001 attributes with processes,
1045 * all the way through to the ivl_target API.
1047 * Divide signal reference counts between rval
1048 * and lval references.