Merge branch 'master' into verilog-ams
[sverilog.git] / expr_synth.cc
blob3f079fc5c73a70fce5f448fc4ffcfc116ff7f376
1 /*
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)
8 * any later version.
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 # include "config.h"
21 # include "compiler.h"
23 # include <iostream>
25 # include "netlist.h"
26 # include "netmisc.h"
27 # include "ivl_assert.h"
29 NetNet* convert_to_real_const(Design*des, NetExpr*expr, NetExpr*obj)
31 NetNet* sig;
33 if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
34 verireal vrl(tmp->value().as_double());
35 NetECReal rlval(vrl);
36 sig = rlval.synthesize(des);
37 } else {
38 cerr << obj->get_fileline() << ": sorry: Cannot convert "
39 "bit based value (" << *expr << ") to real." << endl;
40 des->errors += 1;
41 sig = 0;
44 return sig;
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,
50 NetExpr*obj)
52 if (left->expr_type() == IVL_VT_REAL ||
53 right->expr_type() == IVL_VT_REAL) {
54 real_args = true;
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);
60 } else {
61 lsig = convert_to_real_const(des, left, obj);
64 if (right->expr_type() == IVL_VT_REAL) {
65 rsig = right->synthesize(des);
66 } else {
67 rsig = convert_to_real_const(des, right, obj);
69 } else {
70 real_args = false;
71 lsig = left->synthesize(des);
72 rsig = right->synthesize(des);
76 if (lsig == 0 || rsig == 0) return true;
77 else return false;
80 NetNet* NetExpr::synthesize(Design*des)
82 cerr << get_fileline() << ": internal error: cannot synthesize expression: "
83 << *this << endl;
84 des->errors += 1;
85 return 0;
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;
96 bool real_args=false;
97 if (process_binary_args(des, left_, right_, lsig, rsig,
98 real_args, this)) {
99 return 0;
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);
123 switch (op()) {
124 case '+':
125 adder->attribute(perm_string::literal("LPM_Direction"), verinum("ADD"));
126 break;
127 case '-':
128 adder->attribute(perm_string::literal("LPM_Direction"), verinum("SUB"));
129 break;
132 return osig;
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
139 * of the expression.
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;
153 des->errors += 1;
154 return 0;
157 NetScope*scope = lsig->scope();
158 assert(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();
173 NetLogic*gate;
175 switch (op()) {
176 case '&':
177 gate = new NetLogic(scope, oname, 3, NetLogic::AND, width);
178 break;
179 case 'A':
180 gate = new NetLogic(scope, oname, 3, NetLogic::NAND, width);
181 break;
182 case '|':
183 gate = new NetLogic(scope, oname, 3, NetLogic::OR, width);
184 break;
185 case '^':
186 gate = new NetLogic(scope, oname, 3, NetLogic::XOR, width);
187 break;
188 case 'O':
189 gate = new NetLogic(scope, oname, 3, NetLogic::NOR, width);
190 break;
191 case 'X':
192 gate = new NetLogic(scope, oname, 3, NetLogic::XNOR, width);
193 break;
194 default:
195 assert(0);
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);
203 des->add_node(gate);
205 return osig;
208 NetNet* NetEBComp::synthesize(Design*des)
211 NetNet *lsig=0, *rsig=0;
212 unsigned width;
213 bool real_args=false;
214 if (process_binary_args(des, left_, right_, lsig, rsig,
215 real_args, this)) {
216 return 0;
219 if (real_args) {
220 width = 1;
221 } else {
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();
230 assert(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));
249 des->add_node(gate);
250 return osig;
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));
263 des->add_node(gate);
264 return osig;
268 NetCompare*dev = new NetCompare(scope, scope->local_symbol(), width);
269 dev->set_line(*this);
270 des->add_node(dev);
272 connect(dev->pin_DataA(), lsig->pin(0));
273 connect(dev->pin_DataB(), rsig->pin(0));
276 switch (op_) {
277 case '<':
278 connect(dev->pin_ALB(), osig->pin(0));
279 dev->set_signed(signed_compare);
280 break;
281 case '>':
282 connect(dev->pin_AGB(), osig->pin(0));
283 dev->set_signed(signed_compare);
284 break;
285 case 'E': // === ?
286 if (real_args) {
287 cerr << get_fileline() << ": error: Case equality may "
288 "not have real operands." << endl;
289 des->errors += 1;
290 return 0;
292 case 'e': // ==
293 connect(dev->pin_AEB(), osig->pin(0));
294 break;
295 case 'G': // >=
296 connect(dev->pin_AGEB(), osig->pin(0));
297 dev->set_signed(signed_compare);
298 break;
299 case 'L': // <=
300 connect(dev->pin_ALEB(), osig->pin(0));
301 dev->set_signed(signed_compare);
302 break;
303 case 'N': // !==
304 if (real_args) {
305 cerr << get_fileline() << ": error: Case inequality may "
306 "not have real operands." << endl;
307 des->errors += 1;
308 return 0;
310 case 'n': // !=
311 connect(dev->pin_ANEB(), osig->pin(0));
312 break;
314 default:
315 cerr << get_fileline() << ": internal error: cannot synthesize "
316 "comparison: " << *this << endl;
317 des->errors += 1;
318 return 0;
321 return osig;
324 NetNet* NetEBPow::synthesize(Design*des)
326 NetNet *lsig=0, *rsig=0;
327 unsigned width;
328 bool real_args=false;
329 if (process_binary_args(des, left_, right_, lsig, rsig,
330 real_args, this)) {
331 return 0;
334 if (real_args) width = 1;
335 else width = expr_width();
337 NetScope*scope = lsig->scope();
338 assert(scope);
340 NetPow*powr = new NetPow(scope, scope->local_symbol(), width,
341 lsig->vector_width(),
342 rsig->vector_width());
343 des->add_node(powr);
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));
359 return osig;
362 NetNet* NetEBMult::synthesize(Design*des)
364 NetNet *lsig=0, *rsig=0;
365 unsigned width;
366 bool real_args=false;
367 if (process_binary_args(des, left_, right_, lsig, rsig,
368 real_args, this)) {
369 return 0;
372 if (real_args) width = 1;
373 else width = expr_width();
375 NetScope*scope = lsig->scope();
376 assert(scope);
378 NetMult*mult = new NetMult(scope, scope->local_symbol(),
379 width,
380 lsig->vector_width(),
381 rsig->vector_width());
382 des->add_node(mult);
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));
398 return osig;
401 NetNet* NetEBDiv::synthesize(Design*des)
403 NetNet *lsig=0, *rsig=0;
404 unsigned width;
405 bool real_args=false;
406 if (process_binary_args(des, left_, right_, lsig, rsig,
407 real_args, this)) {
408 return 0;
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);
422 switch (op()) {
424 case '/': {
425 NetDivide*div = new NetDivide(scope, scope->local_symbol(),
426 width,
427 lsig->vector_width(),
428 rsig->vector_width());
429 div->set_line(*this);
430 des->add_node(div);
432 connect(div->pin_DataA(), lsig->pin(0));
433 connect(div->pin_DataB(), rsig->pin(0));
434 connect(div->pin_Result(),osig->pin(0));
435 break;
438 case '%': {
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;
444 des->errors += 1;
445 return 0;
447 NetModulo*div = new NetModulo(scope, scope->local_symbol(),
448 width,
449 lsig->vector_width(),
450 rsig->vector_width());
451 div->set_line(*this);
452 des->add_node(div);
454 connect(div->pin_DataA(), lsig->pin(0));
455 connect(div->pin_DataB(), rsig->pin(0));
456 connect(div->pin_Result(),osig->pin(0));
457 break;
460 default: {
461 cerr << get_fileline() << ": internal error: "
462 << "NetEBDiv has unexpeced op() code: "
463 << op() << endl;
464 des->errors += 1;
466 delete osig;
467 return 0;
471 return osig;
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;
486 des->errors += 1;
487 return 0;
490 NetScope*scope = lsig->scope();
491 assert(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);
499 if (op() == 'o') {
501 /* Logic OR can handle the reduction *and* the logical
502 comparison with a single wide OR gate. So handle this
503 magically. */
505 perm_string oname = scope->local_symbol();
507 NetLogic*olog = new NetLogic(scope, oname,
508 lsig->pin_count()+rsig->pin_count()+1,
509 NetLogic::OR, 1);
511 connect(osig->pin(0), olog->pin(0));
513 unsigned pin = 1;
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));
521 des->add_node(olog);
523 } else {
524 assert(op() == 'a');
526 /* Create the logic AND gate. This is a single bit
527 output, with inputs for each of the operands. */
528 NetLogic*olog;
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));
534 des->add_node(olog);
536 /* XXXX Here, I need to reduce the parameters with
537 reduction or. */
540 /* By this point, the left and right parameters have been
541 reduced to single bit values. Now we just connect them to
542 the logic gate. */
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));
551 return osig;
554 NetNet* NetEBShift::synthesize(Design*des)
556 eval_expr(right_);
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;
567 des->errors += 1;
568 return 0;
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();
583 if (op() == 'r')
584 shift = 0-shift;
586 if (shift == 0)
587 return lsig;
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(),
604 znum);
605 des->add_node(zcon);
607 /* Detect the special case that the shift is the size of
608 the whole expression. Simply connect the pad to the
609 osig and escape. */
610 if (ushift >= osig->vector_width()) {
611 connect(zcon->pin(0), osig->pin(0));
612 return osig;
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,
625 part_width,
626 NetPartSelect::VP);
627 des->add_node(psel);
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);
639 des->add_node(ccat);
641 connect(ccat->pin(0), osig->pin(0));
642 if (shift > 0) {
643 // Left shift.
644 connect(ccat->pin(1), zsig->pin(0));
645 connect(ccat->pin(2), psig->pin(0));
646 } else {
647 // Right shift
648 connect(ccat->pin(1), psig->pin(0));
649 connect(ccat->pin(2), zsig->pin(0));
652 return osig;
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);
669 des->add_node(dev);
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));
678 return osig;
681 NetNet* NetEConcat::synthesize(Design*des)
683 /* First, synthesize the operands. */
684 NetNet**tmp = new NetNet*[parms_.count()];
685 bool flag = true;
686 for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
687 tmp[idx] = parms_[idx]->synthesize(des);
688 if (tmp[idx] == 0)
689 flag = false;
692 if (flag == false)
693 return 0;
695 assert(tmp[0]);
696 NetScope*scope = tmp[0]->scope();
697 assert(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));
716 cur_pin += 1;
720 delete[]tmp;
721 return osig;
724 NetNet* NetEConst::synthesize(Design*des)
726 NetScope*scope = des->find_root_scope();
727 assert(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));
739 des->add_node(con);
740 return osig;
744 * Create a NetLiteral object to represent real valued constants.
746 NetNet* NetECReal::synthesize(Design*des)
748 NetScope*scope = des->find_root_scope();
749 assert(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_);
760 des->add_node(con);
761 con->set_line(*this);
763 connect(osig->pin(0), con->pin(0));
764 return osig;
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;
781 des->errors += 1;
782 return 0;
785 NetScope*scope = isig->scope();
786 assert(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();
795 NetLogic*gate;
797 switch (op()) {
798 case '~':
799 gate = new NetLogic(scope, oname, 2, NetLogic::NOT, width);
800 break;
801 default:
802 assert(0);
805 connect(osig->pin(0), gate->pin(0));
806 connect(isig->pin(0), gate->pin(1));
808 des->add_node(gate);
810 return osig;
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;
823 des->errors += 1;
824 return 0;
827 NetScope*scope = isig->scope();
828 assert(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;
837 switch (op()) {
838 case 'N':
839 case '!':
840 rtype = NetUReduce::NOR;
841 break;
842 case '&':
843 rtype = NetUReduce::AND;
844 break;
845 case '|':
846 rtype = NetUReduce::OR;
847 break;
848 case '^':
849 rtype = NetUReduce::XOR;
850 break;
851 case 'A':
852 rtype = NetUReduce::XNOR;
853 break;
854 case 'X':
855 rtype = NetUReduce::XNOR;
856 break;
857 default:
858 cerr << get_fileline() << ": internal error: "
859 << "Unable to synthesize " << *this << "." << endl;
860 return 0;
863 NetUReduce*gate = new NetUReduce(scope, scope->local_symbol(),
864 rtype, isig->vector_width());
866 des->add_node(gate);
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));
871 return osig;
874 NetNet* NetESelect::synthesize(Design *des)
877 NetNet*sub = expr_->synthesize(des);
879 if (sub == 0) return 0;
881 NetScope*scope = sub->scope();
883 NetNet*off = 0;
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.
888 if (base_ != 0) {
889 off = base_->synthesize(des);
891 NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
892 sel->set_line(*this);
893 des->add_node(sel);
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);
900 sub = tmp;
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
909 // are done.
910 if (sub->vector_width() == expr_width())
911 return sub;
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);
923 if (has_sign()) {
924 NetSignExtend*pad = new NetSignExtend(scope,
925 scope->local_symbol(),
926 expr_width());
927 pad->set_line(*this);
928 des->add_node(pad);
930 connect(pad->pin(1), sub->pin(0));
931 connect(pad->pin(0), net->pin(0));
932 net->set_signed(true);
934 } else {
936 NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
937 expr_width(), 2);
938 cat->set_line(*this);
939 des->add_node(cat);
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(),
945 pad);
946 con->set_line(*this);
947 des->add_node(con);
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));
961 return net;
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;
985 des->errors += 1;
986 return 0;
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;
990 des->errors += 1;
991 return 0;
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());
1017 des->add_node(mux);
1019 return osig;
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)
1030 if (word_ == 0)
1031 return net_;
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));
1048 } else {
1049 unsigned selwid = word_->expr_width();
1051 NetArrayDq*mux = new NetArrayDq(scope, scope->local_symbol(),
1052 net_, selwid);
1053 mux->set_line(*this);
1054 des->add_node(mux);
1056 NetNet*index_net = word_->synthesize(des);
1057 connect(mux->pin_Address(), index_net->pin(0));
1059 connect(tmp->pin(0), mux->pin_Result());
1061 return tmp;
1064 NetNet* NetESFunc::synthesize(Design*des)
1066 cerr << get_fileline() << ": sorry: cannot synthesize system function: "
1067 << *this << " in this context" << endl;
1068 des->errors += 1;
1069 return 0;
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);
1080 if (tmp == 0) {
1081 cerr << get_fileline() << ": error: Unable to synthesize "
1082 "port " << idx << " of call to "
1083 << func_->basename() << "." << endl;
1084 errors = true;
1085 des->errors += 1;
1086 continue;
1088 eparms[idx] = tmp;
1090 if (errors) return 0;
1092 NetUserFunc*net = new NetUserFunc(scope_, scope_->local_symbol(), func_);
1093 net->set_line(*this);
1094 des->add_node(net);
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));
1111 return osig;