Permalink
Newer
Older
100644 3066 lines (2596 sloc) 89.9 KB
2
* Copyright (c) 1999-2007 Stephen Williams (steve@icarus.com)
3
*
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.
9
*
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.
14
*
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
18
*/
19
#ifdef HAVE_CVS_IDENT
20
#ident "$Id: elab_net.cc,v 1.192 2007/01/16 05:44:15 steve Exp $"
23
# include "config.h"
24
25
# include "PExpr.h"
26
# include "netlist.h"
27
# include "netmisc.h"
28
# include "compiler.h"
30
# include <iostream>
31
32
/*
33
* This is a state flag that determines whether an elaborate_net must
34
* report an error when it encounters an unsized number. Normally, it
35
* is fine to make an unsized number as small as it can be, but there
36
* are a few cases where the size must be fully self-determined. For
37
* example, within a {...} (concatenation) operator.
38
*/
39
static bool must_be_self_determined_flag = false;
40
41
NetNet* PExpr::elaborate_net(Design*des, NetScope*scope, unsigned,
42
const NetExpr*,
43
const NetExpr*,
44
const NetExpr*,
45
Link::strength_t,
46
Link::strength_t) const
47
{
48
cerr << get_line() << ": error: Unable to elaborate `"
49
<< *this << "' as gates." << endl;
50
return 0;
51
}
52
53
/*
54
* Elaborating binary operations generally involves elaborating the
55
* left and right expressions, then making an output wire and
56
* connecting the lot together with the right kind of gate.
57
*/
58
NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
59
unsigned width,
60
const NetExpr* rise,
61
const NetExpr* fall,
62
const NetExpr* decay,
63
Link::strength_t drive0,
64
Link::strength_t drive1) const
65
{
66
switch (op_) {
68
return elaborate_net_mul_(des, scope, width, rise, fall, decay);
70
return elaborate_net_mod_(des, scope, width, rise, fall, decay);
71
case '/':
72
return elaborate_net_div_(des, scope, width, rise, fall, decay);
73
case '+':
74
case '-':
75
return elaborate_net_add_(des, scope, width, rise, fall, decay);
76
case '|': // Bitwise OR
77
case '&':
78
case '^':
79
case 'A': // Bitwise NAND (~&)
80
case 'O': // Bitwise NOR (~|)
Jan 27, 2003
81
case 'X': // Exclusive NOR
82
return elaborate_net_bit_(des, scope, width, rise, fall, decay);
83
case 'E': // === (case equals)
84
case 'e': // ==
85
case 'N': // !== (case not-equals)
86
case 'n': // !=
87
case '<':
88
case '>':
89
case 'L': // <=
90
case 'G': // >=
91
return elaborate_net_cmp_(des, scope, width, rise, fall, decay);
92
case 'a': // && (logical and)
93
case 'o': // || (logical or)
94
return elaborate_net_log_(des, scope, width, rise, fall, decay);
95
case 'l': // <<
96
case 'r': // >>
98
return elaborate_net_shift_(des, scope, width, rise, fall, decay);
101
NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
102
*rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
103
if (lsig == 0) {
104
cerr << get_line() << ": error: Cannot elaborate ";
105
left_->dump(cerr);
106
cerr << endl;
107
return 0;
108
}
109
if (rsig == 0) {
110
cerr << get_line() << ": error: Cannot elaborate ";
111
right_->dump(cerr);
112
cerr << endl;
113
return 0;
114
}
115
116
NetNet*osig;
117
118
switch (op_) {
119
case '^': // XOR
120
case 'X': // XNOR
121
case '&': // AND
122
case '|': // Bitwise OR
124
break;
125
126
case 'E': // === (Case equals)
127
case 'e': // ==
128
case 'n': // !=
129
case '<':
130
case '>':
131
case 'G': // >=
132
case 'L': // <=
134
break;
135
136
case '+':
137
assert(0);
138
break;
139
140
case 'l':
141
case 'r':
143
assert(0);
144
break;
145
default:
146
cerr << get_line() << ": internal error: unsupported"
147
" combinational operator (" << op_ << ")." << endl;
148
des->errors += 1;
149
osig = 0;
150
}
151
152
return osig;
153
}
154
155
/*
156
* Elaborate the structural +/- as an AddSub object. Connect DataA and
157
* DataB to the parameters, and connect the output signal to the
158
* Result. In this context, the device is a combinational adder with
159
* fixed direction, so leave Add_Sub unconnected and set the
160
* LPM_Direction property.
161
*/
162
NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
163
unsigned lwidth,
164
const NetExpr* rise,
165
const NetExpr* fall,
166
const NetExpr* decay) const
168
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
169
*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
170
if (lsig == 0) {
171
cerr << get_line() << ": error: Cannot elaborate ";
172
left_->dump(cerr);
173
cerr << endl;
174
return 0;
175
}
176
if (rsig == 0) {
177
cerr << get_line() << ": error: Cannot elaborate ";
178
right_->dump(cerr);
179
cerr << endl;
180
return 0;
181
}
182
183
NetNet*osig;
184
185
unsigned width = lsig->vector_width();
186
if (rsig->vector_width() > lsig->vector_width())
187
width = rsig->vector_width();
Feb 8, 2001
189
190
/* The owidth is the output width of the lpm_add_sub
Aug 28, 2003
191
device. If the desired width is greater then the width of
192
the operands, then widen the adder and let code below pad
194
unsigned owidth = width;
195
switch (op_) {
196
case '+':
197
if (lwidth > owidth) {
198
owidth = lwidth;
200
}
201
break;
202
case '-':
203
if (lwidth > owidth) {
204
owidth = lwidth;
205
width = lwidth;
206
}
207
break;
208
default:
209
assert(0);
210
}
Feb 8, 2001
211
212
bool expr_signed = lsig->get_signed() && rsig->get_signed();
214
// Pad out the operands, if necessary, the match the width of
215
// the adder device.
216
if (lsig->vector_width() < width)
217
if (expr_signed)
218
lsig = pad_to_width_signed(des, lsig, width);
219
else
220
lsig = pad_to_width(des, lsig, width);
222
if (rsig->vector_width() < width)
223
if (expr_signed)
224
rsig = pad_to_width_signed(des, rsig, width);
225
else
226
rsig = pad_to_width(des, rsig, width);
228
// Check that the argument types match.
229
if (lsig->data_type() != rsig->data_type()) {
230
cerr << get_line() << ": error: Arguments of add/sub "
231
<< "have different data types." << endl;
232
cerr << get_line() << ": : Left argument is "
233
<< lsig->data_type() << ", right argument is "
234
<< rsig->data_type() << "." << endl;
235
des->errors += 1;
236
}
237
238
// Make the adder as wide as the widest operand
239
osig = new NetNet(scope, scope->local_symbol(),
240
NetNet::WIRE, owidth);
241
osig->data_type(lsig->data_type());
242
osig->set_signed(expr_signed);
243
osig->local_flag(true);
244
if (debug_elaborate) {
245
cerr << get_line() << ": debug: Elaborate NetAddSub "
246
<< "width=" << width << " lwidth=" << lwidth
247
<< endl;
248
}
249
NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
250
251
// Connect the adder to the various parts.
252
connect(lsig->pin(0), adder->pin_DataA());
253
connect(rsig->pin(0), adder->pin_DataB());
254
connect(osig->pin(0), adder->pin_Result());
255
#ifdef XXXX
256
if (owidth > width)
257
connect(osig->pin(width), adder->pin_Cout());
259
NetNode*gate = adder;
260
gate->rise_time(rise);
261
gate->fall_time(fall);
262
gate->decay_time(decay);
263
des->add_node(gate);
264
265
gate->attribute(perm_string::literal("LPM_Direction"),
266
verinum(op_ == '+' ? "ADD" : "SUB"));
267
268
return osig;
269
}
270
271
/*
272
* Elaborate various bitwise logic operators. These are all similar in
273
* that they take operants of equal width, and each bit does not
274
* affect any other bits. Also common about all this is how bit widths
275
* of the operands are handled, when they do not match.
276
*/
277
NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
279
const NetExpr* rise,
280
const NetExpr* fall,
281
const NetExpr* decay) const
283
NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
284
*rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
285
if (lsig == 0) {
286
cerr << get_line() << ": error: Cannot elaborate ";
287
left_->dump(cerr);
288
cerr << endl;
289
return 0;
290
}
291
if (rsig == 0) {
292
cerr << get_line() << ": error: Cannot elaborate ";
293
right_->dump(cerr);
294
cerr << endl;
295
return 0;
296
}
297
298
if (lsig->vector_width() < rsig->vector_width())
299
lsig = pad_to_width(des, lsig, rsig->vector_width());
300
if (rsig->vector_width() < lsig->vector_width())
301
rsig = pad_to_width(des, rsig, lsig->vector_width());
303
if (lsig->data_type() != rsig->data_type()) {
304
cerr << get_line() << ": error: Types of "
305
<< "operands of " << op_ << " do not match: "
306
<< lsig->data_type() << " vs. " << rsig->data_type()
307
<< endl;
308
des->errors += 1;
309
return 0;
310
}
311
312
if (lsig->vector_width() != rsig->vector_width()) {
313
cerr << get_line() << ": internal error: lsig width ("
314
<< lsig->vector_width() << ") != rsig pin width ("
315
<< rsig->vector_width() << ")." << endl;
316
des->errors += 1;
317
return 0;
318
}
319
320
assert(lsig->vector_width() == rsig->vector_width());
322
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE,
323
lsig->vector_width());
324
osig->local_flag(true);
325
osig->data_type( lsig->data_type() );
327
NetLogic::TYPE gtype=NetLogic::AND;
329
case '^': gtype = NetLogic::XOR; break; // XOR
330
case 'X': gtype = NetLogic::XNOR; break; // XNOR
331
case '&': gtype = NetLogic::AND; break; // AND
332
case 'A': gtype = NetLogic::NAND; break; // NAND (~&)
333
case '|': gtype = NetLogic::OR; break; // Bitwise OR
334
case 'O': gtype = NetLogic::NOR; break; // Bitwise NOR
335
default: assert(0);
338
NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
339
3, gtype, osig->vector_width());
340
gate->set_line(*this);
341
connect(gate->pin(0), osig->pin(0));
342
connect(gate->pin(1), lsig->pin(0));
343
connect(gate->pin(2), rsig->pin(0));
344
gate->rise_time(rise);
345
gate->fall_time(fall);
346
gate->decay_time(decay);
347
des->add_node(gate);
348
349
return osig;
350
}
351
352
/*
353
* This function attempts to handle the special case of == or !=
354
* compare to a constant value. The caller has determined already that
355
* one of the operands is a NetEConst, and has already elaborated the
356
* other.
357
*/
358
static NetNet* compare_eq_constant(Design*des, NetScope*scope,
359
NetNet*lsig, NetEConst*rexp,
360
char op_code,
361
const NetExpr* rise,
362
const NetExpr* fall,
363
const NetExpr* decay)
364
{
365
if (op_code != 'e' && op_code != 'n')
366
return 0;
367
368
verinum val = rexp->value();
369
370
/* Abandon special case if there are x or z bits in the
371
constant. We can't get the right behavior out of
372
OR/NOR in this case. */
373
if (! val.is_defined())
374
return 0;
375
376
if (val.len() < lsig->vector_width())
377
val = verinum(val, lsig->vector_width());
379
/* Look for the very special case that we know the compare
380
results a priori due to different high bits, that are
381
constant pad in the signal. */
382
if (val.len() > lsig->vector_width()) {
383
unsigned idx = lsig->vector_width();
384
verinum::V lpad = verinum::V0;
385
386
while (idx < val.len()) {
387
if (val.get(idx) != lpad) {
388
verinum oval (op_code == 'e'
389
? verinum::V0
390
: verinum::V1,
391
1);
392
NetEConst*ogate = new NetEConst(oval);
393
NetNet*osig = ogate->synthesize(des);
394
osig->data_type(lsig->data_type());
396
397
if (debug_elaborate)
398
cerr << lsig->get_line() << ": debug: "
399
<< "Equality replaced with "
400
<< oval << " due to high pad mismatch"
401
<< endl;
402
403
return osig;
404
}
405
406
idx +=1;
407
}
408
}
409
410
unsigned zeros = 0;
411
unsigned ones = 0;
412
for (unsigned idx = 0 ; idx < lsig->vector_width() ; idx += 1) {
413
if (val.get(idx) == verinum::V0)
414
zeros += 1;
415
if (val.get(idx) == verinum::V1)
416
ones += 1;
417
}
418
419
/* Handle the special case that the gate is a compare that can
420
be replaces with a reduction AND or NOR. */
421
422
if (ones == 0 || zeros == 0) {
423
NetUReduce::TYPE type;
424
425
if (zeros > 0) {
426
type = op_code == 'e'? NetUReduce::NOR : NetUReduce::OR;
427
428
if (debug_elaborate)
429
cerr << lsig->get_line() << ": debug: "
430
<< "Replace net==" << val << " equality with "
431
<< zeros << "-input reduction [N]OR gate." << endl;
432
433
} else {
434
type = op_code == 'e'? NetUReduce::AND : NetUReduce::NAND;
435
436
if (debug_elaborate)
437
cerr << lsig->get_line() << ": debug: "
438
<< "Replace net==" << val << " equality with "
439
<< ones << "-input reduction AND gate." << endl;
440
}
441
442
NetUReduce*red = new NetUReduce(scope, scope->local_symbol(),
443
type, zeros+ones);
444
des->add_node(red);
445
red->set_line(*lsig);
446
447
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
448
NetNet::WIRE, 0, 0);
449
tmp->data_type(lsig->data_type());
450
tmp->local_flag(true);
451
tmp->set_line(*lsig);
453
connect(red->pin(1), lsig->pin(0));
454
connect(red->pin(0), tmp->pin(0));
455
return tmp;
458
if (debug_elaborate)
459
cerr << lsig->get_line() << ": debug: "
460
<< "Give up trying to replace net==" << val
461
<< " equality with "
462
<< ones << "-input AND and "
463
<< zeros << "-input NOR gates." << endl;
464
465
return 0;
469
* Elaborate the various binary comparison operators. The comparison
470
* operators return a single bit result, no matter what, so the left
471
* and right values can have their own size. The only restriction is
472
* that they have the same size.
474
NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
475
unsigned lwidth,
476
const NetExpr* rise,
477
const NetExpr* fall,
478
const NetExpr* decay) const
481
/* Elaborate the operands of the compare first as expressions
482
(so that the eval_tree method can reduce constant
483
expressions, including parameters) then turn those results
484
into synthesized nets. */
485
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth);
486
if (lexp == 0) {
487
cerr << get_line() << ": error: Cannot elaborate ";
488
left_->dump(cerr);
489
cerr << endl;
490
return 0;
491
}
493
NetExpr*rexp = elab_and_eval(des, scope, right_, lwidth);
494
if (rexp == 0) {
495
cerr << get_line() << ": error: Cannot elaborate ";
496
right_->dump(cerr);
497
cerr << endl;
498
return 0;
499
}
500
501
/* Choose the operand width to be the width of the widest
502
self-determined operand. */
503
unsigned operand_width = lexp->expr_width();
504
if (rexp->expr_width() > operand_width)
505
operand_width = rexp->expr_width();
506
507
lexp->set_width(operand_width);
508
lexp = pad_to_width(lexp, operand_width);
509
rexp->set_width(operand_width);
510
rexp = pad_to_width(rexp, operand_width);
512
NetNet*lsig = 0;
513
NetNet*rsig = 0;
514
515
/* Handle the special case that the right or left
516
sub-expression is a constant value. The compare_eq_constant
517
function will return an elaborated result if it can make
518
use of the situation, or 0 if it cannot. */
519
if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
520
521
lsig = lexp->synthesize(des);
522
if (lsig == 0) {
523
cerr << get_line() << ": internal error: "
524
"Cannot elaborate net for " << *lexp << endl;
527
assert(lsig);
528
delete lexp;
529
lexp = 0;
530
531
NetNet*osig = compare_eq_constant(des, scope,
532
lsig, tmp, op_,
533
rise, fall, decay);
534
if (osig != 0) {
535
delete rexp;
536
return osig;
537
}
538
}
539
540
if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
541
542
rsig = rexp->synthesize(des);
543
assert(rsig);
544
delete rexp;
545
546
NetNet*osig = compare_eq_constant(des, scope,
547
rsig, tmp, op_,
548
rise, fall, decay);
549
if (osig != 0) {
550
delete lexp;
551
return osig;
552
}
553
}
554
555
if (lsig == 0) {
556
lsig = lexp->synthesize(des);
557
assert(lsig);
558
delete lexp;
559
}
560
561
if (rsig == 0) {
562
rsig = rexp->synthesize(des);
563
assert(rsig);
564
delete rexp;
565
}
567
unsigned dwidth = lsig->vector_width();
568
if (rsig->vector_width() > dwidth) dwidth = rsig->vector_width();
570
/* Operands of binary compare need to be padded to equal
571
size. Figure the pad bit needed to extend the narrowest
572
vector. */
573
if (lsig->vector_width() < dwidth)
574
lsig = pad_to_width(des, lsig, dwidth);
575
if (rsig->vector_width() < dwidth)
576
rsig = pad_to_width(des, rsig, dwidth);
579
NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
580
osig->data_type(IVL_VT_LOGIC);
581
osig->set_line(*this);
582
osig->local_flag(true);
583
584
NetNode*gate;
585
586
switch (op_) {
587
case '<':
588
case '>':
589
case 'L':
590
case 'G': {
591
NetCompare*cmp = new
592
NetCompare(scope, scope->local_symbol(), dwidth);
593
connect(cmp->pin_DataA(), lsig->pin(0));
594
connect(cmp->pin_DataB(), rsig->pin(0));
596
switch (op_) {
597
case '<':
598
connect(cmp->pin_ALB(), osig->pin(0));
599
break;
600
case '>':
601
connect(cmp->pin_AGB(), osig->pin(0));
602
break;
603
case 'L':
604
connect(cmp->pin_ALEB(), osig->pin(0));
605
break;
606
case 'G':
607
connect(cmp->pin_AGEB(), osig->pin(0));
608
break;
609
}
610
/* If both operands are signed, then do a signed
611
compare. */
612
if (lsig->get_signed() && rsig->get_signed())
613
cmp->set_signed(true);
614
615
gate = cmp;
616
break;
617
}
618
619
case 'E': // Case equals (===)
620
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
621
connect(gate->pin(0), osig->pin(0));
622
connect(gate->pin(1), lsig->pin(0));
623
connect(gate->pin(2), rsig->pin(0));
626
case 'N': // Case equals (!==)
627
gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
628
connect(gate->pin(0), osig->pin(0));
629
connect(gate->pin(1), lsig->pin(0));
630
connect(gate->pin(2), rsig->pin(0));
632
633
case 'e': // ==
634
635
/* Handle the special case of single bit compare with a
636
single XNOR gate. This is easy and direct. */
637
if (dwidth == 1) {
638
gate = new NetLogic(scope, scope->local_symbol(),
639
3, NetLogic::XNOR, 1);
640
connect(gate->pin(0), osig->pin(0));
641
connect(gate->pin(1), lsig->pin(0));
642
connect(gate->pin(2), rsig->pin(0));
643
break;
644
}
645
646
if (debug_elaborate) {
647
cerr << get_line() << ": debug: Elaborate net == gate."
648
<< endl;
649
}
650
651
/* Oh well, do the general case with a NetCompare. */
652
{ NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
654
connect(cmp->pin_DataA(), lsig->pin(0));
655
connect(cmp->pin_DataB(), rsig->pin(0));
656
connect(cmp->pin_AEB(), osig->pin(0));
657
gate = cmp;
658
}
659
break;
660
661
case 'n': // !=
662
663
/* Handle the special case of single bit compare with a
664
single XOR gate. This is easy and direct. */
665
if (dwidth == 1) {
666
gate = new NetLogic(scope, scope->local_symbol(),
668
connect(gate->pin(0), osig->pin(0));
669
connect(gate->pin(1), lsig->pin(0));
670
connect(gate->pin(2), rsig->pin(0));
671
break;
672
}
673
674
/* Oh well, do the general case with a NetCompare. */
675
{ NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
677
connect(cmp->pin_DataA(), lsig->pin(0));
678
connect(cmp->pin_DataB(), rsig->pin(0));
679
connect(cmp->pin_ANEB(), osig->pin(0));
680
gate = cmp;
681
}
682
break;
683
684
default:
685
assert(0);
686
}
687
688
gate->rise_time(rise);
689
gate->fall_time(fall);
690
gate->decay_time(decay);
691
des->add_node(gate);
692
693
return osig;
694
}
695
Jan 27, 2003
697
* Elaborate a divider gate. This function create a NetDivide gate
698
* which has exactly the right sized DataA, DataB and Result ports. If
699
* the l-value is wider then the result, then pad.
701
NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
702
unsigned lwidth,
703
const NetExpr* rise,
704
const NetExpr* fall,
705
const NetExpr* decay) const
707
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
708
if (lsig == 0) return 0;
709
NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
710
if (rsig == 0) return 0;
711
712
713
// Check the l-value width. If it is unspecified, then use the
714
// largest operand width as the l-value width. Restrict the
715
// result width to the width of the largest operand, because
716
// there is no value is excess divider.
717
718
unsigned rwidth = lwidth;
719
720
if (rwidth == 0) {
721
rwidth = lsig->vector_width();
722
if (rsig->vector_width() > rwidth)
723
rwidth = rsig->vector_width();
724
725
lwidth = rwidth;
726
}
727
728
if ((rwidth > lsig->vector_width()) && (rwidth > rsig->vector_width())) {
729
rwidth = lsig->vector_width();
730
if (rsig->vector_width() > rwidth)
731
rwidth = rsig->vector_width();
734
/* The arguments of a divide must have the same type. */
735
if (lsig->data_type() != rsig->data_type()) {
736
cerr << get_line() << ": error: Arguments of divide "
737
<< "have different data types." << endl;
738
cerr << get_line() << ": : Left argument is "
739
<< lsig->data_type() << ", right argument is "
740
<< rsig->data_type() << "." << endl;
741
des->errors += 1;
742
}
743
744
ivl_variable_type_t data_type = lsig->data_type();
745
746
// Create a device with the calculated dimensions.
747
NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth,
748
lsig->vector_width(),
749
rsig->vector_width());
750
des->add_node(div);
751
752
div->set_signed(lsig->get_signed() && rsig->get_signed());
753
754
// Connect the left and right inputs of the divider to the
755
// nets that are the left and right expressions.
756
757
connect(div->pin_DataA(), lsig->pin(0));
758
connect(div->pin_DataB(), rsig->pin(0));
760
761
// Make an output signal that is the width of the l-value.
762
// Due to above calculation of rwidth, we know that the result
763
// will be no more then the l-value, so it is safe to connect
764
// all the result pins to the osig.
765
766
NetNet*osig = new NetNet(scope, scope->local_symbol(),
767
NetNet::IMPLICIT, lwidth);
768
osig->local_flag(true);
769
osig->data_type(data_type);
770
osig->set_signed(div->get_signed());
772
connect(div->pin_Result(), osig->pin(0));
774
775
return osig;
776
}
777
778
/*
779
* Elaborate a modulo gate.
780
*/
781
NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
782
unsigned lwidth,
783
const NetExpr* rise,
784
const NetExpr* fall,
785
const NetExpr* decay) const
787
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
788
if (lsig == 0) return 0;
789
NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
790
if (rsig == 0) return 0;
791
792
/* The arguments of a modulus must have the same type. */
793
if (lsig->data_type() != rsig->data_type()) {
794
cerr << get_line() << ": error: Arguments of modulus "
795
<< "have different data types." << endl;
796
cerr << get_line() << ": : Left argument is "
797
<< lsig->data_type() << ", right argument is "
798
<< rsig->data_type() << "." << endl;
799
des->errors += 1;
800
}
801
802
ivl_variable_type_t data_type = lsig->data_type();
803
804
/* rwidth is result width. */
805
unsigned rwidth = lwidth;
806
if (rwidth == 0) {
807
rwidth = lsig->vector_width();
808
if (rsig->vector_width() > rwidth)
809
rwidth = rsig->vector_width();
810
811
lwidth = rwidth;
814
NetModulo*mod = new NetModulo(scope, scope->local_symbol(), rwidth,
815
lsig->vector_width(),
816
rsig->vector_width());
817
mod->set_line(*this);
818
des->add_node(mod);
819
820
connect(mod->pin_DataA(), lsig->pin(0));
821
connect(mod->pin_DataB(), rsig->pin(0));
823
NetNet*osig = new NetNet(scope, scope->local_symbol(),
824
NetNet::IMPLICIT, rwidth);
825
osig->set_line(*this);
826
osig->data_type(data_type);
827
osig->local_flag(true);
828
829
connect(mod->pin_Result(), osig->pin(0));
830
831
return osig;
832
}
833
834
NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
835
unsigned lwidth,
836
const NetExpr* rise,
837
const NetExpr* fall,
838
const NetExpr* decay) const
839
{
840
NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
841
NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
842
if (lsig == 0) {
843
cerr << get_line() << ": error: Cannot elaborate ";
844
left_->dump(cerr);
845
cerr << endl;
846
return 0;
847
}
848
if (rsig == 0) {
849
cerr << get_line() << ": error: Cannot elaborate ";
850
right_->dump(cerr);
851
cerr << endl;
852
return 0;
853
}
854
855
NetLogic*gate;
856
switch (op_) {
857
case 'a':
858
gate = new NetLogic(scope, scope->local_symbol(),
860
break;
861
case 'o':