Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 2168 lines (1870 sloc) 66.039 kb
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
1 /*
b734ecf Macintosh compilers do not support ident.
steve authored
2 * Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
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 */
b734ecf Macintosh compilers do not support ident.
steve authored
19 #if !defined(WINNT) && !defined(macintosh)
b825f8d Create a config.h.in file to hold all the config
steve authored
20 #ident "$Id: elab_net.cc,v 1.73 2001/07/25 03:10:48 steve Exp $"
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
21 #endif
22
b825f8d Create a config.h.in file to hold all the config
steve authored
23 # include "config.h"
24
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
25 # include "PExpr.h"
26 # include "netlist.h"
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
27 # include "netmisc.h"
48de739 Switch to control warnings.
steve authored
28 # include "compiler.h"
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
29
b825f8d Create a config.h.in file to hold all the config
steve authored
30 # include <iostream>
31
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
32 /*
33 * Elaborating binary operations generally involves elaborating the
34 * left and right expressions, then making an output wire and
35 * connecting the lot together with the right kind of gate.
36 */
37 NetNet* PEBinary::elaborate_net(Design*des, const string&path,
38 unsigned width,
39 unsigned long rise,
40 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
41 unsigned long decay,
42 Link::strength_t drive0,
43 Link::strength_t drive1) const
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
44 {
45 switch (op_) {
aa8908c Multiplication all the way to simulation.
steve authored
46 case '*':
47 return elaborate_net_mul_(des, path, width, rise, fall, decay);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
48 case '%':
49 return elaborate_net_mod_(des, path, width, rise, fall, decay);
694ff93 Add support for integer division.
steve authored
50 case '/':
51 return elaborate_net_div_(des, path, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
52 case '+':
53 case '-':
54 return elaborate_net_add_(des, path, width, rise, fall, decay);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
55 case '|': // Bitwise OR
56 case '&':
57 case '^':
58 case 'X': // Exclusing NOR
59 return elaborate_net_bit_(des, path, width, rise, fall, decay);
b8c5aff Generate !== an an inverted ===
steve authored
60 case 'E': // === (case equals)
61 case 'e': // ==
62 case 'N': // !== (case not-equals)
63 case 'n': // !=
513ade9 Support combinatorial comparators.
steve authored
64 case '<':
65 case '>':
66 case 'L': // <=
67 case 'G': // >=
206b37e Fix NetConst being set to zero width, and clean
steve authored
68 return elaborate_net_cmp_(des, path, width, rise, fall, decay);
ced7cc6 Structural logical or.
steve authored
69 case 'a': // && (logical and)
70 case 'o': // || (logical or)
71 return elaborate_net_log_(des, path, width, rise, fall, decay);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
72 case 'l': // <<
73 case 'r': // >>
74 return elaborate_net_shift_(des, path, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
75 }
76
77 NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0),
78 *rsig = right_->elaborate_net(des, path, width, 0, 0, 0);
79 if (lsig == 0) {
80 cerr << get_line() << ": error: Cannot elaborate ";
81 left_->dump(cerr);
82 cerr << endl;
83 return 0;
84 }
85 if (rsig == 0) {
86 cerr << get_line() << ": error: Cannot elaborate ";
87 right_->dump(cerr);
88 cerr << endl;
89 return 0;
90 }
91
92 NetNet*osig;
93 NetNode*gate;
94 NetNode*gate_t;
95
96 switch (op_) {
97 case '^': // XOR
57d28e4 Support structural XNOR.
steve authored
98 case 'X': // XNOR
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
99 case '&': // AND
100 case '|': // Bitwise OR
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
101 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
102 break;
103
104 case 'E': // === (Case equals)
105 case 'e': // ==
106 case 'n': // !=
513ade9 Support combinatorial comparators.
steve authored
107 case '<':
108 case '>':
109 case 'G': // >=
110 case 'L': // <=
206b37e Fix NetConst being set to zero width, and clean
steve authored
111 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
112 break;
113
114 case '+':
115 assert(0);
116 break;
117
118 case 'l':
119 case 'r':
1624afe Add support for the LPM_CLSHIFT device.
steve authored
120 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
121 break;
122 default:
123 cerr << get_line() << ": internal error: unsupported"
124 " combinational operator (" << op_ << ")." << endl;
125 des->errors += 1;
126 osig = 0;
127 }
128
129 if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
130 delete tmp;
131 if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
132 delete tmp;
133
134 return osig;
135 }
136
137 /*
138 * Elaborate the structural +/- as an AddSub object. Connect DataA and
139 * DataB to the parameters, and connect the output signal to the
140 * Result. In this context, the device is a combinational adder with
141 * fixed direction, so leave Add_Sub unconnected and set the
142 * LPM_Direction property.
143 */
144 NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
145 unsigned lwidth,
146 unsigned long rise,
147 unsigned long fall,
148 unsigned long decay) const
149 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
150 NetScope*scope = des->find_scope(path);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
151 NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0),
152 *rsig = right_->elaborate_net(des, path, lwidth, 0, 0, 0);
153 if (lsig == 0) {
154 cerr << get_line() << ": error: Cannot elaborate ";
155 left_->dump(cerr);
156 cerr << endl;
157 return 0;
158 }
159 if (rsig == 0) {
160 cerr << get_line() << ": error: Cannot elaborate ";
161 right_->dump(cerr);
162 cerr << endl;
163 return 0;
164 }
165
166 NetNet*osig;
167 NetNode*gate;
168 NetNode*gate_t;
169
170 string name = des->local_symbol(path);
171 unsigned width = lsig->pin_count();
172 if (rsig->pin_count() > lsig->pin_count())
173 width = rsig->pin_count();
174
d78c739 Remove dead code.
steve authored
175
4124273 Handle some special cases of unary 2's complement,
steve authored
176 /* The owidth is the output width of the lpm_add_sub
177 device. If the desired with is greater then the width of
178 the operands, then widen the adder and let code below pad
179 the operands. If this is an adder, we can take advantage of
180 the carry bit. */
181 unsigned owidth = width;
182 switch (op_) {
183 case '+':
184 if (lwidth > owidth) {
185 owidth = lwidth;
186 width = lwidth-1;
187 }
188 break;
189 case '-':
190 if (lwidth > owidth) {
191 owidth = lwidth;
192 width = lwidth;
193 }
194 break;
195 default:
196 assert(0);
197 }
d78c739 Remove dead code.
steve authored
198
d54cc14 Simulate carry output on adders.
steve authored
199
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
200 // Pad out the operands, if necessary, the match the width of
201 // the adder device.
202 if (lsig->pin_count() < width)
2b0aaec FreeBSD port has a maintainer now.
steve authored
203 lsig = pad_to_width(des, lsig, width);
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
204
205 if (rsig->pin_count() < width)
2b0aaec FreeBSD port has a maintainer now.
steve authored
206 rsig = pad_to_width(des, rsig, width);
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
207
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
208 // Make the adder as wide as the widest operand
4124273 Handle some special cases of unary 2's complement,
steve authored
209 osig = new NetNet(scope, des->local_symbol(path),
210 NetNet::WIRE, owidth);
211 osig->local_flag(true);
f480943 Support structural addition.
steve authored
212 NetAddSub*adder = new NetAddSub(scope, name, width);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
213
214 // Connect the adder to the various parts.
215 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
216 connect(lsig->pin(idx), adder->pin_DataA(idx));
217 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
218 connect(rsig->pin(idx), adder->pin_DataB(idx));
d54cc14 Simulate carry output on adders.
steve authored
219 for (unsigned idx = 0 ; idx < width ; idx += 1)
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
220 connect(osig->pin(idx), adder->pin_Result(idx));
d54cc14 Simulate carry output on adders.
steve authored
221 if (owidth > width)
222 connect(osig->pin(width), adder->pin_Cout());
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
223
224 gate = adder;
225 gate->rise_time(rise);
226 gate->fall_time(fall);
227 gate->decay_time(decay);
228 des->add_node(gate);
229
230 switch (op_) {
231 case '+':
232 gate->attribute("LPM_Direction", "ADD");
233 break;
234 case '-':
235 gate->attribute("LPM_Direction", "SUB");
236 break;
237 }
238
239
240 return osig;
241 }
242
243 /*
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
244 * Elaborate various bitwise logic operators. These are all similar in
245 * that they take operants of equal width, and each bit does not
246 * affect any other bits. Also common about all this is how bit widths
247 * of the operands are handled, when they do not match.
248 */
249 NetNet* PEBinary::elaborate_net_bit_(Design*des, const string&path,
250 unsigned width,
251 unsigned long rise,
252 unsigned long fall,
253 unsigned long decay) const
254 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
255 NetScope*scope = des->find_scope(path);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
256 NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0),
257 *rsig = right_->elaborate_net(des, path, width, 0, 0, 0);
258 if (lsig == 0) {
259 cerr << get_line() << ": error: Cannot elaborate ";
260 left_->dump(cerr);
261 cerr << endl;
262 return 0;
263 }
264 if (rsig == 0) {
265 cerr << get_line() << ": error: Cannot elaborate ";
266 right_->dump(cerr);
267 cerr << endl;
268 return 0;
269 }
270
271 if (lsig->pin_count() < rsig->pin_count())
2b0aaec FreeBSD port has a maintainer now.
steve authored
272 lsig = pad_to_width(des, lsig, rsig->pin_count());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
273 if (rsig->pin_count() < lsig->pin_count())
2b0aaec FreeBSD port has a maintainer now.
steve authored
274 rsig = pad_to_width(des, rsig, lsig->pin_count());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
275
276 if (lsig->pin_count() != rsig->pin_count()) {
277 cerr << get_line() << ": internal error: lsig pin count ("
278 << lsig->pin_count() << ") != rsig pin count ("
279 << rsig->pin_count() << ")." << endl;
280 des->errors += 1;
281 return 0;
282 }
283
284 assert(lsig->pin_count() == rsig->pin_count());
285
8d8f1e2 Move signal tables to the NetScope class.
steve authored
286 NetNet*osig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE,
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
287 lsig->pin_count());
288 osig->local_flag(true);
289
290 switch (op_) {
291 case '^': // XOR
292 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
293 NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
294 3, NetLogic::XOR);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
295 connect(gate->pin(1), lsig->pin(idx));
296 connect(gate->pin(2), rsig->pin(idx));
297 connect(gate->pin(0), osig->pin(idx));
298 gate->rise_time(rise);
299 gate->fall_time(fall);
300 gate->decay_time(decay);
301 des->add_node(gate);
302 }
303 break;
304
305 case 'X': // XNOR
306 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
307 NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
308 3, NetLogic::XNOR);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
309 connect(gate->pin(1), lsig->pin(idx));
310 connect(gate->pin(2), rsig->pin(idx));
311 connect(gate->pin(0), osig->pin(idx));
312 gate->rise_time(rise);
313 gate->fall_time(fall);
314 gate->decay_time(decay);
315 des->add_node(gate);
316 }
317 break;
318
319 case '&': // AND
320 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
321 NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
322 3, NetLogic::AND);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
323 connect(gate->pin(1), lsig->pin(idx));
324 connect(gate->pin(2), rsig->pin(idx));
325 connect(gate->pin(0), osig->pin(idx));
326 gate->rise_time(rise);
327 gate->fall_time(fall);
328 gate->decay_time(decay);
329 des->add_node(gate);
330 }
331 break;
332
333 case '|': // Bitwise OR
334 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
335 NetLogic*gate = new NetLogic(scope, des->local_symbol(path),
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
336 3, NetLogic::OR);
337 connect(gate->pin(1), lsig->pin(idx));
338 connect(gate->pin(2), rsig->pin(idx));
339 connect(gate->pin(0), osig->pin(idx));
340 gate->rise_time(rise);
341 gate->fall_time(fall);
342 gate->decay_time(decay);
343 des->add_node(gate);
344 }
345 break;
346
347 default:
348 assert(0);
349 }
350
351
352 return osig;
353 }
354
355 /*
3d1ffce Elaborate net widths of constants to as small
steve authored
356 * Elaborate the various binary comparison operators. The comparison
357 * operators return a single bit result, no matter what, so the left
358 * and right values can have their own size. The only restriction is
359 * that they have the same size.
206b37e Fix NetConst being set to zero width, and clean
steve authored
360 */
361 NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
362 unsigned lwidth,
363 unsigned long rise,
364 unsigned long fall,
365 unsigned long decay) const
366 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
367 NetScope*scope = des->find_scope(path);
206b37e Fix NetConst being set to zero width, and clean
steve authored
368 NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0),
369 *rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
370 if (lsig == 0) {
371 cerr << get_line() << ": error: Cannot elaborate ";
372 left_->dump(cerr);
373 cerr << endl;
374 return 0;
375 }
376 if (rsig == 0) {
377 cerr << get_line() << ": error: Cannot elaborate ";
378 right_->dump(cerr);
379 cerr << endl;
380 return 0;
381 }
382
3d1ffce Elaborate net widths of constants to as small
steve authored
383 unsigned dwidth = lsig->pin_count();
384 if (rsig->pin_count() > dwidth) dwidth = rsig->pin_count();
385
386 NetNet*zero = 0;
387 if (lsig->pin_count() != rsig->pin_count()) {
388 NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
389 des->add_node(tmp);
8d8f1e2 Move signal tables to the NetScope class.
steve authored
390 zero = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
3d1ffce Elaborate net widths of constants to as small
steve authored
391 connect(tmp->pin(0), zero->pin(0));
392 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
393
8d8f1e2 Move signal tables to the NetScope class.
steve authored
394 NetNet*osig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
206b37e Fix NetConst being set to zero width, and clean
steve authored
395 osig->local_flag(true);
396
397 NetNode*gate;
3d1ffce Elaborate net widths of constants to as small
steve authored
398 //NetNode*gate_t;
206b37e Fix NetConst being set to zero width, and clean
steve authored
399
400 switch (op_) {
513ade9 Support combinatorial comparators.
steve authored
401 case '<':
402 case '>':
403 case 'L':
404 case 'G': {
3d1ffce Elaborate net widths of constants to as small
steve authored
405 NetCompare*cmp = new
b3a5a0e Generate vvp code for GT and GE comparisons.
steve authored
406 NetCompare(scope, des->local_symbol(path), dwidth);
3d1ffce Elaborate net widths of constants to as small
steve authored
407 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
513ade9 Support combinatorial comparators.
steve authored
408 connect(cmp->pin_DataA(idx), lsig->pin(idx));
3d1ffce Elaborate net widths of constants to as small
steve authored
409 for (unsigned idx = lsig->pin_count(); idx < dwidth ; idx += 1)
410 connect(cmp->pin_DataA(idx), zero->pin(0));
411 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
513ade9 Support combinatorial comparators.
steve authored
412 connect(cmp->pin_DataB(idx), rsig->pin(idx));
3d1ffce Elaborate net widths of constants to as small
steve authored
413 for (unsigned idx = rsig->pin_count(); idx < dwidth ; idx += 1)
414 connect(cmp->pin_DataB(idx), zero->pin(0));
415
513ade9 Support combinatorial comparators.
steve authored
416 switch (op_) {
417 case '<':
418 connect(cmp->pin_ALB(), osig->pin(0));
419 break;
420 case '>':
421 connect(cmp->pin_AGB(), osig->pin(0));
422 break;
423 case 'L':
424 connect(cmp->pin_ALEB(), osig->pin(0));
425 break;
426 case 'G':
427 connect(cmp->pin_AGEB(), osig->pin(0));
428 break;
429 }
430 gate = cmp;
431 break;
432 }
433
206b37e Fix NetConst being set to zero width, and clean
steve authored
434 case 'E': // Case equals (===)
b8c5aff Generate !== an an inverted ===
steve authored
435 case 'N': // Case equals (!==)
206b37e Fix NetConst being set to zero width, and clean
steve authored
436 // The comparison generates gates to bitwise compare
437 // each pair, and AND all the comparison results.
b8c5aff Generate !== an an inverted ===
steve authored
438
76e2c50 Put logic devices into scopes.
steve authored
439 gate = new NetLogic(scope, des->local_symbol(path),
f224ed3 Fix out-of-bound pins for comparator (PR#108)
steve authored
440 1+dwidth,
b8c5aff Generate !== an an inverted ===
steve authored
441 (op_ == 'E')? NetLogic::AND : NetLogic::NAND);
206b37e Fix NetConst being set to zero width, and clean
steve authored
442 connect(gate->pin(0), osig->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
443 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
444 NetCaseCmp*cmp = new NetCaseCmp(des->local_symbol(path));
445
446 if (idx < lsig->pin_count())
447 connect(cmp->pin(1), lsig->pin(idx));
448 else
449 connect(cmp->pin(1), zero->pin(0));
450
451 if (idx < rsig->pin_count())
452 connect(cmp->pin(2), rsig->pin(idx));
453 else
454 connect(cmp->pin(2), zero->pin(0));
455
456 connect(cmp->pin(0), gate->pin(idx+1));
457 des->add_node(cmp);
206b37e Fix NetConst being set to zero width, and clean
steve authored
458
459 // Attach a label to this intermediate wire
8d8f1e2 Move signal tables to the NetScope class.
steve authored
460 NetNet*tmp = new NetNet(scope, des->local_symbol(path),
206b37e Fix NetConst being set to zero width, and clean
steve authored
461 NetNet::WIRE);
462 tmp->local_flag(true);
3d1ffce Elaborate net widths of constants to as small
steve authored
463 connect(cmp->pin(0), tmp->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
464 }
465 break;
466
467
468 case 'e': // ==
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
469
470 /* Handle the special case of single bit compare with a
471 single XNOR gate. This is easy and direct. */
472 if (dwidth == 1) {
76e2c50 Put logic devices into scopes.
steve authored
473 gate = new NetLogic(scope, des->local_symbol(path),
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
474 3, NetLogic::XNOR);
475 connect(gate->pin(0), osig->pin(0));
476 connect(gate->pin(1), lsig->pin(0));
477 connect(gate->pin(2), rsig->pin(0));
478 break;
479 }
480
481 /* Oh well, do the general case. */
76e2c50 Put logic devices into scopes.
steve authored
482 gate = new NetLogic(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
483 1+dwidth,NetLogic::AND);
206b37e Fix NetConst being set to zero width, and clean
steve authored
484 connect(gate->pin(0), osig->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
485 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
486 NetLogic*cmp = new NetLogic(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
487 3, NetLogic::XNOR);
488 if (idx < lsig->pin_count())
489 connect(cmp->pin(1), lsig->pin(idx));
490 else
491 connect(cmp->pin(1), zero->pin(0));
492
493 if (idx < rsig->pin_count())
494 connect(cmp->pin(2), rsig->pin(idx));
495 else
496 connect(cmp->pin(2), zero->pin(0));
497
498 connect(cmp->pin(0), gate->pin(idx+1));
499 des->add_node(cmp);
500
8d8f1e2 Move signal tables to the NetScope class.
steve authored
501 NetNet*tmp = new NetNet(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
502 NetNet::WIRE);
503 tmp->local_flag(true);
504 connect(cmp->pin(0), tmp->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
505 }
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
506
206b37e Fix NetConst being set to zero width, and clean
steve authored
507 break;
508
509 case 'n': // !=
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
510
511 /* Handle the special case of single bit compare with a
512 single XOR gate. This is easy and direct. */
513 if (dwidth == 1) {
76e2c50 Put logic devices into scopes.
steve authored
514 gate = new NetLogic(scope, des->local_symbol(path),
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
515 3, NetLogic::XOR);
516 connect(gate->pin(0), osig->pin(0));
517 connect(gate->pin(1), lsig->pin(0));
518 connect(gate->pin(2), rsig->pin(0));
519 break;
520 }
521
76e2c50 Put logic devices into scopes.
steve authored
522 gate = new NetLogic(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
523 1+dwidth, NetLogic::OR);
206b37e Fix NetConst being set to zero width, and clean
steve authored
524 connect(gate->pin(0), osig->pin(0));
cdb3eb7 Connect all the l and r bits of a NE expression.
steve authored
525 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
526 NetLogic*cmp = new NetLogic(scope, des->local_symbol(path),
527 3, NetLogic::XOR);
3d1ffce Elaborate net widths of constants to as small
steve authored
528 if (idx < lsig->pin_count())
529 connect(cmp->pin(1), lsig->pin(idx));
530 else
531 connect(cmp->pin(1), zero->pin(0));
532
533 if (idx < rsig->pin_count())
534 connect(cmp->pin(2), rsig->pin(idx));
535 else
536 connect(cmp->pin(2), zero->pin(0));
537
538 connect(cmp->pin(0), gate->pin(idx+1));
539 des->add_node(cmp);
540
8d8f1e2 Move signal tables to the NetScope class.
steve authored
541 NetNet*tmp = new NetNet(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
542 NetNet::WIRE);
543 tmp->local_flag(true);
544 connect(cmp->pin(0), tmp->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
545 }
546 break;
547
548 default:
549 assert(0);
550 }
551
552 gate->rise_time(rise);
553 gate->fall_time(fall);
554 gate->decay_time(decay);
555 des->add_node(gate);
556
557 return osig;
558 }
559
694ff93 Add support for integer division.
steve authored
560 /*
8ee00ec Fix net division to cope with small output sizes.
steve authored
561 * Elaborate a divider gate. This function create a NetDevide gate
562 * which has exactly the right sized DataA, DataB and Result ports. If
563 * the l-value is wider then the result, then pad.
694ff93 Add support for integer division.
steve authored
564 */
565 NetNet* PEBinary::elaborate_net_div_(Design*des, const string&path,
566 unsigned lwidth,
567 unsigned long rise,
568 unsigned long fall,
569 unsigned long decay) const
570 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
571 NetScope*scope = des->find_scope(path);
572 assert(scope);
694ff93 Add support for integer division.
steve authored
573 NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0);
574 if (lsig == 0) return 0;
575 NetNet*rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
576 if (rsig == 0) return 0;
577
8ee00ec Fix net division to cope with small output sizes.
steve authored
578
579 // Check the l-value width. If it is unspecified, then use the
580 // largest operand width as the l-value width. Restrict the
581 // result width to the width of the largest operand, because
582 // there is no value is excess divider.
583
584 unsigned rwidth = lwidth;
585
586 if (rwidth == 0) {
587 rwidth = lsig->pin_count();
588 if (rsig->pin_count() > rwidth)
589 rwidth = rsig->pin_count();
590
591 lwidth = rwidth;
592 }
593
594 if ((rwidth > lsig->pin_count()) && (rwidth > rsig->pin_count())) {
595 rwidth = lsig->pin_count();
596 if (rsig->pin_count() > rwidth)
597 rwidth = rsig->pin_count();
598 }
599
600 // Create a device with the calculated dimensions.
694ff93 Add support for integer division.
steve authored
601 NetDivide*div = new NetDivide(des->local_symbol(path), rwidth,
602 lsig->pin_count(),
603 rsig->pin_count());
604 des->add_node(div);
605
8ee00ec Fix net division to cope with small output sizes.
steve authored
606
607 // Connect the left and right inputs of the divider to the
608 // nets that are the left and right expressions.
609
694ff93 Add support for integer division.
steve authored
610 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
611 connect(div->pin_DataA(idx), lsig->pin(idx));
612 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
613 connect(div->pin_DataB(idx), rsig->pin(idx));
614
8ee00ec Fix net division to cope with small output sizes.
steve authored
615
616 // Make an output signal that is the width of the l-value.
617 // Due to above calculation of rwidth, we know that the result
618 // will be no more then the l-value, so it is safe to connect
619 // all the result pins to the osig.
620
8d8f1e2 Move signal tables to the NetScope class.
steve authored
621 NetNet*osig = new NetNet(scope, des->local_symbol(path),
694ff93 Add support for integer division.
steve authored
622 NetNet::IMPLICIT, lwidth);
623 osig->local_flag(true);
624
8ee00ec Fix net division to cope with small output sizes.
steve authored
625 for (unsigned idx = 0 ; idx < rwidth ; idx += 1)
694ff93 Add support for integer division.
steve authored
626 connect(div->pin_Result(idx), osig->pin(idx));
627
8ee00ec Fix net division to cope with small output sizes.
steve authored
628
629 // If the lvalue is larger then the result, then pad the
630 // output with constant 0. This can happen for example in
631 // cases like this:
632 // wire [3;0] a, b;
633 // wire [7:0] r = a / b;
634
635 if (rwidth < osig->pin_count()) {
694ff93 Add support for integer division.
steve authored
636 NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
637 des->add_node(tmp);
8ee00ec Fix net division to cope with small output sizes.
steve authored
638 for (unsigned idx = rwidth ; idx < osig->pin_count() ; idx += 1)
694ff93 Add support for integer division.
steve authored
639 connect(osig->pin(idx), tmp->pin(0));
640 }
641
642 return osig;
643 }
644
89d7176 Add support for modulus (Eric Aardoom)
steve authored
645 /*
646 * Elaborate a modulo gate.
647 */
648 NetNet* PEBinary::elaborate_net_mod_(Design*des, const string&path,
649 unsigned lwidth,
650 unsigned long rise,
651 unsigned long fall,
652 unsigned long decay) const
653 {
654 NetScope*scope = des->find_scope(path);
655 assert(scope);
656 NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0);
657 if (lsig == 0) return 0;
658 NetNet*rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
659 if (rsig == 0) return 0;
660
661 unsigned rwidth = lsig->pin_count();
662 if (rsig->pin_count() > rwidth)
663 rwidth = rsig->pin_count();
664 NetModulo*mod = new NetModulo(des->local_symbol(path), rwidth,
665 lsig->pin_count(),
666 rsig->pin_count());
667 des->add_node(mod);
668
669 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
670 connect(mod->pin_DataA(idx), lsig->pin(idx));
671 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
672 connect(mod->pin_DataB(idx), rsig->pin(idx));
673
674 if (lwidth == 0) lwidth = rwidth;
675 NetNet*osig = new NetNet(scope, des->local_symbol(path),
676 NetNet::IMPLICIT, lwidth);
677 osig->local_flag(true);
678
679 unsigned cnt = osig->pin_count();
680 if (cnt > rwidth) cnt = rwidth;
681
682 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
683 connect(mod->pin_Result(idx), osig->pin(idx));
684
685 /* If the lvalue is larger then the result, then pad the
686 output with constant 0. */
687 if (cnt < osig->pin_count()) {
688 NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
689 des->add_node(tmp);
690 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
691 connect(osig->pin(idx), tmp->pin(0));
692 }
693
694 return osig;
695 }
696
ced7cc6 Structural logical or.
steve authored
697 NetNet* PEBinary::elaborate_net_log_(Design*des, const string&path,
698 unsigned lwidth,
699 unsigned long rise,
700 unsigned long fall,
701 unsigned long decay) const
702 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
703 NetScope*scope = des->find_scope(path);
704 assert(scope);
705
ced7cc6 Structural logical or.
steve authored
706 NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0),
707 *rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
708 if (lsig == 0) {
709 cerr << get_line() << ": error: Cannot elaborate ";
710 left_->dump(cerr);
711 cerr << endl;
712 return 0;
713 }
714 if (rsig == 0) {
715 cerr << get_line() << ": error: Cannot elaborate ";
716 right_->dump(cerr);
717 cerr << endl;
718 return 0;
719 }
720
721 NetLogic*gate;
722 NetLogic*gate_t;
723 switch (op_) {
724 case 'a':
76e2c50 Put logic devices into scopes.
steve authored
725 gate = new NetLogic(scope, des->local_symbol(path),
726 3, NetLogic::AND);
ced7cc6 Structural logical or.
steve authored
727 break;
728 case 'o':
76e2c50 Put logic devices into scopes.
steve authored
729 gate = new NetLogic(scope, des->local_symbol(path),
730 3, NetLogic::OR);
ced7cc6 Structural logical or.
steve authored
731 break;
732 default:
733 assert(0);
734 }
735 gate->rise_time(rise);
736 gate->fall_time(fall);
737 gate->decay_time(decay);
738
739 // The first OR gate returns 1 if the left value is true...
740 if (lsig->pin_count() > 1) {
76e2c50 Put logic devices into scopes.
steve authored
741 gate_t = new NetLogic(scope, des->local_symbol(path),
ced7cc6 Structural logical or.
steve authored
742 1+lsig->pin_count(), NetLogic::OR);
743 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
744 connect(gate_t->pin(idx+1), lsig->pin(idx));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
745
ced7cc6 Structural logical or.
steve authored
746 connect(gate->pin(1), gate_t->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
747
748 /* The reduced logical value is a new nexus, create a
749 temporary signal to represent it. */
8d8f1e2 Move signal tables to the NetScope class.
steve authored
750 NetNet*tmp = new NetTmp(scope, des->local_symbol(path));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
751 connect(gate->pin(1), tmp->pin(0));
752
ced7cc6 Structural logical or.
steve authored
753 des->add_node(gate_t);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
754
ced7cc6 Structural logical or.
steve authored
755 } else {
756 connect(gate->pin(1), lsig->pin(0));
757 }
758
759 // The second OR gate returns 1 if the right value is true...
760 if (rsig->pin_count() > 1) {
76e2c50 Put logic devices into scopes.
steve authored
761 gate_t = new NetLogic(scope, des->local_symbol(path),
ced7cc6 Structural logical or.
steve authored
762 1+rsig->pin_count(), NetLogic::OR);
763 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
764 connect(gate_t->pin(idx+1), rsig->pin(idx));
765 connect(gate->pin(2), gate_t->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
766
767 /* The reduced logical value is a new nexus, create a
768 temporary signal to represent it. */
8d8f1e2 Move signal tables to the NetScope class.
steve authored
769 NetNet*tmp = new NetTmp(scope, des->local_symbol(path));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
770 connect(gate->pin(2), tmp->pin(0));
771
ced7cc6 Structural logical or.
steve authored
772 des->add_node(gate_t);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
773
ced7cc6 Structural logical or.
steve authored
774 } else {
775 connect(gate->pin(2), rsig->pin(0));
776 }
777
778 // The output is the AND/OR of the two logic values.
8d8f1e2 Move signal tables to the NetScope class.
steve authored
779 NetNet*osig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
ced7cc6 Structural logical or.
steve authored
780 osig->local_flag(true);
781 connect(gate->pin(0), osig->pin(0));
782 des->add_node(gate);
783 return osig;
784 }
785
aa8908c Multiplication all the way to simulation.
steve authored
786 NetNet* PEBinary::elaborate_net_mul_(Design*des, const string&path,
787 unsigned lwidth,
788 unsigned long rise,
789 unsigned long fall,
790 unsigned long decay) const
791 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
792 NetScope*scope = des->find_scope(path);
793 assert(scope);
794
4124273 Handle some special cases of unary 2's complement,
steve authored
795 NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0);
aa8908c Multiplication all the way to simulation.
steve authored
796 if (lsig == 0) return 0;
4124273 Handle some special cases of unary 2's complement,
steve authored
797 NetNet*rsig = right_->elaborate_net(des, path, lwidth, 0, 0, 0);
aa8908c Multiplication all the way to simulation.
steve authored
798 if (rsig == 0) return 0;
799
4124273 Handle some special cases of unary 2's complement,
steve authored
800 unsigned rwidth = lwidth;
4b82d26 Add support for structural multiply in t-dll.
steve authored
801 NetMult*mult = new NetMult(scope, des->local_symbol(path), rwidth,
aa8908c Multiplication all the way to simulation.
steve authored
802 lsig->pin_count(),
803 rsig->pin_count());
804 des->add_node(mult);
805
806 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
807 connect(mult->pin_DataA(idx), lsig->pin(idx));
808 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
809 connect(mult->pin_DataB(idx), rsig->pin(idx));
810
811 if (lwidth == 0) lwidth = rwidth;
8d8f1e2 Move signal tables to the NetScope class.
steve authored
812 NetNet*osig = new NetNet(scope, des->local_symbol(path),
aa8908c Multiplication all the way to simulation.
steve authored
813 NetNet::IMPLICIT, lwidth);
814 osig->local_flag(true);
815
816 unsigned cnt = osig->pin_count();
817 if (cnt > rwidth) cnt = rwidth;
818
819 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
820 connect(mult->pin_Result(idx), osig->pin(idx));
821
822 /* If the lvalue is larger then the result, then pad the
823 output with constant 0. */
824 if (cnt < osig->pin_count()) {
825 NetConst*tmp = new NetConst(des->local_symbol(path), verinum::V0);
826 des->add_node(tmp);
827 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
828 connect(osig->pin(idx), tmp->pin(0));
829 }
830
831 return osig;
832 }
833
1624afe Add support for the LPM_CLSHIFT device.
steve authored
834 NetNet* PEBinary::elaborate_net_shift_(Design*des, const string&path,
835 unsigned lwidth,
836 unsigned long rise,
837 unsigned long fall,
838 unsigned long decay) const
839 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
840 NetScope*scope = des->find_scope(path);
841 assert(scope);
842
1624afe Add support for the LPM_CLSHIFT device.
steve authored
843 NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0);
844 if (lsig == 0) return 0;
845
9e5ff89 Add structural reduction NAND,
steve authored
846 if (lsig->pin_count() > lwidth)
847 lwidth = lsig->pin_count();
848
1624afe Add support for the LPM_CLSHIFT device.
steve authored
849 /* Handle the special case of a constant shift amount. There
850 is no reason in this case to create a gate at all, just
851 connect the lsig to the osig with the bit positions
852 shifted. */
853 if (verinum*rval = right_->eval_const(des, path)) {
854 assert(rval->is_defined());
855 unsigned dist = rval->as_ulong();
4124273 Handle some special cases of unary 2's complement,
steve authored
856 if (dist > lwidth)
857 dist = lwidth;
1624afe Add support for the LPM_CLSHIFT device.
steve authored
858
859 /* Very special case, constant 0 shift. */
860 if (dist == 0) return lsig;
861
8d8f1e2 Move signal tables to the NetScope class.
steve authored
862 NetNet*osig = new NetNet(scope, des->local_symbol(path),
4124273 Handle some special cases of unary 2's complement,
steve authored
863 NetNet::WIRE, lwidth);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
864 osig->local_flag(true);
865
866 NetConst*zero = new NetConst(des->local_symbol(path), verinum::V0);
867 des->add_node(zero);
868
869 if (op_ == 'l') {
870 unsigned idx;
871 for (idx = 0 ; idx < dist ; idx += 1)
872 connect(osig->pin(idx), zero->pin(0));
4124273 Handle some special cases of unary 2's complement,
steve authored
873 for ( ; (idx<lwidth) && ((idx-dist) < lsig->pin_count())
874 ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
875 connect(osig->pin(idx), lsig->pin(idx-dist));
4124273 Handle some special cases of unary 2's complement,
steve authored
876 for ( ; idx < lwidth ; idx += 1)
877 connect(osig->pin(idx), zero->pin(0));
1624afe Add support for the LPM_CLSHIFT device.
steve authored
878
879 } else {
880 assert(op_ == 'r');
881 unsigned idx;
882 unsigned keep = lsig->pin_count()-dist;
883 for (idx = 0 ; idx < keep ; idx += 1)
884 connect(osig->pin(idx), lsig->pin(idx+dist));
4124273 Handle some special cases of unary 2's complement,
steve authored
885 for (idx = keep ; idx < lwidth ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
886 connect(osig->pin(idx), zero->pin(0));
887 }
888
889 return osig;
890 }
891
9e5ff89 Add structural reduction NAND,
steve authored
892 // Calculate the number of useful bits for the shift amount,
893 // and elaborate the right_ expression as the shift amount.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
894 unsigned dwid = 0;
9e5ff89 Add structural reduction NAND,
steve authored
895 while ((1 << dwid) < lwidth)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
896 dwid += 1;
897
898 NetNet*rsig = right_->elaborate_net(des, path, dwid, 0, 0, 0);
899 if (rsig == 0) return 0;
900
9e5ff89 Add structural reduction NAND,
steve authored
901 // Make the shift device itself, and the output
902 // NetNet. Connect the Result output pins to the osig signal
bcaa122 handle left shifter in dll output.
steve authored
903 NetCLShift*gate = new NetCLShift(scope, des->local_symbol(path),
9e5ff89 Add structural reduction NAND,
steve authored
904 lwidth, rsig->pin_count());
1624afe Add support for the LPM_CLSHIFT device.
steve authored
905
8d8f1e2 Move signal tables to the NetScope class.
steve authored
906 NetNet*osig = new NetNet(scope, des->local_symbol(path),
9e5ff89 Add structural reduction NAND,
steve authored
907 NetNet::WIRE, lwidth);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
908 osig->local_flag(true);
909
9e5ff89 Add structural reduction NAND,
steve authored
910 for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
911 connect(osig->pin(idx), gate->pin_Result(idx));
9e5ff89 Add structural reduction NAND,
steve authored
912
913 // Connect the lsig (the left expression) to the Data input,
914 // and pad it if necessary with constant zeros.
915 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
916 connect(lsig->pin(idx), gate->pin_Data(idx));
9e5ff89 Add structural reduction NAND,
steve authored
917
918 if (lsig->pin_count() < lwidth) {
919 NetConst*zero = new NetConst(des->local_symbol(path), verinum::V0);
8d8f1e2 Move signal tables to the NetScope class.
steve authored
920 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path));
9e5ff89 Add structural reduction NAND,
steve authored
921 des->add_node(zero);
ba7fdb5 Add a signal to nexus of padding constant.
steve authored
922 connect(zero->pin(0), tmp->pin(0));
9e5ff89 Add structural reduction NAND,
steve authored
923 for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
924 connect(zero->pin(0), gate->pin_Data(idx));
1624afe Add support for the LPM_CLSHIFT device.
steve authored
925 }
926
9e5ff89 Add structural reduction NAND,
steve authored
927 // Connect the rsig (the shift amount expression) to the
928 // Distance input.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
929 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
930 connect(rsig->pin(idx), gate->pin_Distance(idx));
931
932 if (op_ == 'r') {
ca6631f Fix connection of Direction of LMP_CLSHIFT
steve authored
933 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path));
1624afe Add support for the LPM_CLSHIFT device.
steve authored
934 NetConst*dir = new NetConst(des->local_symbol(path), verinum::V1);
935 connect(dir->pin(0), gate->pin_Direction());
ca6631f Fix connection of Direction of LMP_CLSHIFT
steve authored
936 connect(tmp->pin(0), gate->pin_Direction());
1624afe Add support for the LPM_CLSHIFT device.
steve authored
937 des->add_node(dir);
938 }
939
940 des->add_node(gate);
941
942 return osig;
943 }
944
cdb99e7 Elaborate net repeat concatenations.
steve authored
945 /*
946 * The concatenation operator, as a net, is a wide signal that is
947 * connected to all the pins of the elaborated expression nets.
948 */
949 NetNet* PEConcat::elaborate_net(Design*des, const string&path,
950 unsigned,
951 unsigned long rise,
952 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
953 unsigned long decay,
954 Link::strength_t drive0,
955 Link::strength_t drive1) const
cdb99e7 Elaborate net repeat concatenations.
steve authored
956 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
957 NetScope*scope = des->find_scope(path);
958 assert(scope);
959
cdb99e7 Elaborate net repeat concatenations.
steve authored
960 svector<NetNet*>nets (parms_.count());
961 unsigned pins = 0;
962 unsigned errors = 0;
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
963 unsigned repeat = 1;
cdb99e7 Elaborate net repeat concatenations.
steve authored
964
965 if (repeat_) {
966 verinum*rep = repeat_->eval_const(des, path);
967 if (rep == 0) {
968 cerr << get_line() << ": internal error: Unable to "
969 << "evaluate constant repeat expression." << endl;
970 des->errors += 1;
971 return 0;
972 }
973
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
974 repeat = rep->as_ulong();
cdb99e7 Elaborate net repeat concatenations.
steve authored
975
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
976 if (repeat == 0) {
977 cerr << get_line() << ": error: Invalid repeat value."
978 << endl;
979 des->errors += 1;
980 delete rep;
981 return 0;
cdb99e7 Elaborate net repeat concatenations.
steve authored
982 }
983 }
984
985 /* Elaborate the operands of the concatenation. */
986 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
987
f526d23 Check for missing concat subexpressions (PR#11)
steve authored
988 if (parms_[idx] == 0) {
989 cerr << get_line() << ": error: Empty expressions "
990 << "not allowed in concatenations." << endl;
991 errors += 1;
992 continue;
993 }
994
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
995 /* Look for the special case of an unsized number in a
996 concatenation expression. Mark this as an error, but
997 allow elaboration to continue to see if I can find
998 more errors. */
999
1000 if (PENumber*tmp = dynamic_cast<PENumber*>(parms_[idx])) {
1001 if (tmp->value().has_len() == false) {
1002 cerr << get_line() << ": error: Number "
1003 << tmp->value() << " with indefinite size"
1004 << " in concatenation." << endl;
1005 errors += 1;
1006 }
1007 }
1008
cdb99e7 Elaborate net repeat concatenations.
steve authored
1009 nets[idx] = parms_[idx]->elaborate_net(des, path, 0,
1010 rise,fall,decay);
1011 if (nets[idx] == 0)
1012 errors += 1;
1013 else
1014 pins += nets[idx]->pin_count();
1015 }
1016
1017 /* If any of the sub expressions failed to elaborate, then
1018 delete all those that did and abort myself. */
1019 if (errors) {
1020 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
1021 if (nets[idx]) delete nets[idx];
1022 }
1023 des->errors += 1;
1024 return 0;
1025 }
1026
1027 /* Make the temporary signal that connects to all the
1028 operands, and connect it up. Scan the operands of the
1029 concat operator from least significant to most significant,
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1030 which is opposite from how they are given in the list.
1031
1032 Allow for a repeat count other then 1 by repeating the
1033 connect loop as many times as necessary. */
1034
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1035 NetNet*osig = new NetNet(scope, des->local_symbol(path),
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1036 NetNet::IMPLICIT, pins * repeat);
1037
cdb99e7 Elaborate net repeat concatenations.
steve authored
1038 pins = 0;
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1039 for (unsigned rpt = 0 ; rpt < repeat ; rpt += 1)
1040 for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
1041 NetNet*cur = nets[idx-1];
1042 for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
1043 connect(osig->pin(pins), cur->pin(pin));
1044 pins += 1;
1045 }
cdb99e7 Elaborate net repeat concatenations.
steve authored
1046 }
1047
1048 osig->local_flag(true);
1049 return osig;
1050 }
1051
a81dcd7 Support memories in continuous assignments.
steve authored
1052 NetNet* PEIdent::elaborate_net(Design*des, const string&path,
1053 unsigned lwidth,
1054 unsigned long rise,
1055 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1056 unsigned long decay,
1057 Link::strength_t drive0,
1058 Link::strength_t drive1) const
a81dcd7 Support memories in continuous assignments.
steve authored
1059 {
80b8ea9 Put implicitly defined signals in the scope.
steve authored
1060 NetScope*scope = des->find_scope(path);
69612ce Move memories to the NetScope object.
steve authored
1061 NetNet*sig = des->find_signal(scope, text_);
a81dcd7 Support memories in continuous assignments.
steve authored
1062
1063 if (sig == 0) {
1064 /* If the identifier is a memory instead of a signal,
1065 then handle it elsewhere. Create a RAM. */
69612ce Move memories to the NetScope object.
steve authored
1066 if (NetMemory*mem = des->find_memory(scope, text_))
a81dcd7 Support memories in continuous assignments.
steve authored
1067 return elaborate_net_ram_(des, path, mem, lwidth,
1068 rise, fall, decay);
1069
1070
e7efc27 Redesign the implementation of scopes and parameters.
steve authored
1071 if (const NetExpr*pe = des->find_parameter(scope, text_)) {
a81dcd7 Support memories in continuous assignments.
steve authored
1072
1073 const NetEConst*pc = dynamic_cast<const NetEConst*>(pe);
1074 assert(pc);
1075 verinum pvalue = pc->value();
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1076 sig = new NetNet(scope, path+"."+text_, NetNet::IMPLICIT,
a81dcd7 Support memories in continuous assignments.
steve authored
1077 pc->expr_width());
65ae928 NetConst can now hold wide constants.
steve authored
1078 NetConst*cp = new NetConst(des->local_symbol(path), pvalue);
1079 des->add_node(cp);
1080 for (unsigned idx = 0; idx < sig->pin_count(); idx += 1)
1081 connect(sig->pin(idx), cp->pin(idx));
a81dcd7 Support memories in continuous assignments.
steve authored
1082
1083 } else {
1084
80b8ea9 Put implicitly defined signals in the scope.
steve authored
1085 sig = new NetNet(scope, path+"."+text_, NetNet::IMPLICIT, 1);
48de739 Switch to control warnings.
steve authored
1086
1087 if (warn_implicit)
1088 cerr << get_line() << ": warning: implicit "
5276752 Build task outputs as lval instead of nets. (PR#98)
steve authored
1089 "definition of wire " << path << "." <<
48de739 Switch to control warnings.
steve authored
1090 text_ << "." << endl;
a81dcd7 Support memories in continuous assignments.
steve authored
1091 }
1092 }
1093
1094 assert(sig);
1095
1096 if (msb_ && lsb_) {
1097 verinum*mval = msb_->eval_const(des, path);
1098 if (mval == 0) {
1099 cerr << msb_->get_line() << ": error: unable to "
1100 "evaluate constant expression: " << *msb_ <<
1101 endl;
1102 des->errors += 1;
1103 return 0;
1104 }
1105
1106 verinum*lval = lsb_->eval_const(des, path);
1107 if (lval == 0) {
1108 cerr << lsb_->get_line() << ": error: unable to "
1109 "evaluate constant expression: " << *lsb_ <<
1110 endl;
1111 delete mval;
1112 des->errors += 1;
1113 return 0;
1114 }
1115
1116 assert(mval);
1117 assert(lval);
1118 unsigned midx = sig->sb_to_idx(mval->as_long());
1119 unsigned lidx = sig->sb_to_idx(lval->as_long());
1120
2a08824 Detect muxing Vz as a bufufN.
steve authored
1121 /* This is a part select, create a new NetNet object
1122 that connects to just the desired parts of the
1123 identifier. Make sure the NetNet::Type is compatible
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1124 with the sig type.
1125
1126 Be careful to check the bit ordering. If the msb is
1127 less significant then the msb, then the source is
1128 broken. I can hack it in order to go on, but report
1129 an error. */
1130
1131 if (midx < lidx) {
1132 cerr << get_line() << ": error: part select "
1133 << sig->name() << "[" << mval->as_long() << ":"
1134 << lval->as_long() << "] "
1135 << "has bit order reversed." << endl;
1136 des->errors += 1;
a81dcd7 Support memories in continuous assignments.
steve authored
1137
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1138 unsigned tmp = midx;
1139 midx = lidx;
1140 lidx = tmp;
1141 }
a81dcd7 Support memories in continuous assignments.
steve authored
1142
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1143 NetNet*tmp = new NetNet(scope, des->local_symbol(path),
1144 sig->type(), midx-lidx+1);
1145 tmp->local_flag(true);
2b903f5 Detect part select out of range in nets. (PR#138)
steve authored
1146
1147 /* Check that the bit or part select of the signal is
1148 within the range of the part. The lidx is the
1149 normalized index of the LSB, so that plus the desired
1150 width must be <= the width of the references signal. */
1151 if ((lidx + tmp->pin_count()) > sig->pin_count()) {
1152 cerr << get_line() << ": error: bit/part select ["
1153 << mval->as_long() << ":" << lval->as_long()
1154 << "] out of range for " << sig->name() << endl;
1155 des->errors += 1;
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1156 return sig;
1157 }
a81dcd7 Support memories in continuous assignments.
steve authored
1158
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1159 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1160 connect(tmp->pin(idx-lidx), sig->pin(idx));
2a08824 Detect muxing Vz as a bufufN.
steve authored
1161
f2997d7 Detect reverse bit order in part select. (PR#33)
steve authored
1162 sig = tmp;
a81dcd7 Support memories in continuous assignments.
steve authored
1163
1164
1165 } else if (msb_) {
1166 verinum*mval = msb_->eval_const(des, path);
1167 if (mval == 0) {
3ce86f5 Make error message include error: prefix.
steve authored
1168 cerr << get_line() << ": error: index of " << text_ <<
a81dcd7 Support memories in continuous assignments.
steve authored
1169 " needs to be constant in this context." <<
1170 endl;
1171 des->errors += 1;
1172 return 0;
1173 }
1174 assert(mval);
1175 unsigned idx = sig->sb_to_idx(mval->as_long());
1176 if (idx >= sig->pin_count()) {
3ce86f5 Make error message include error: prefix.
steve authored
1177 cerr << get_line() << ": error: index " << sig->name() <<
a81dcd7 Support memories in continuous assignments.
steve authored
1178 "[" << mval->as_long() << "] out of range." << endl;
1179 des->errors += 1;
1180 idx = 0;
1181 }
2a08824 Detect muxing Vz as a bufufN.
steve authored
1182
1183 /* This is a bit select, create a compatible NetNet with
1184 a single bit that links to the selected bit of the
1185 expression. */
1186 NetNet*tmp = new NetNet(scope, des->local_symbol(path),
1187 sig->type(), 1);
1188 tmp->local_flag(true);
1189
a81dcd7 Support memories in continuous assignments.
steve authored
1190 connect(tmp->pin(0), sig->pin(idx));
1191 sig = tmp;
1192 }
1193
1194 return sig;
1195 }
1196
1197 /*
1198 * When I run into an identifier in an expression that referrs to a
1199 * memory, create a RAM port object.
1200 */
1201 NetNet* PEIdent::elaborate_net_ram_(Design*des, const string&path,
1202 NetMemory*mem, unsigned lwidth,
1203 unsigned long rise,
1204 unsigned long fall,
1205 unsigned long decay) const
1206 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1207 NetScope*scope = des->find_scope(path);
1208 assert(scope);
1209
a81dcd7 Support memories in continuous assignments.
steve authored
1210 if (msb_ == 0) {
1211 cerr << get_line() << ": error: memory reference without"
1212 " the required index expression." << endl;
1213 des->errors += 1;
1214 return 0;
1215 }
1216
1217 NetNet*adr = msb_->elaborate_net(des, path, 0, 0, 0, 0);
1218 if (adr == 0)
1219 return 0;
1220
1221
1222 NetRamDq*ram = new NetRamDq(des->local_symbol(mem->name()),
1223 mem, adr->pin_count());
1224 des->add_node(ram);
1225
1226 for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
1227 connect(ram->pin_Address(idx), adr->pin(idx));
1228
eeabc72 Make sure tmp net gets connected to ramdq output
steve authored
1229 NetNet*osig = new NetNet(scope, des->local_symbol(mem->name()),
1230 NetNet::IMPLICIT, ram->width());
1231 osig->local_flag(true);
a81dcd7 Support memories in continuous assignments.
steve authored
1232
1233 for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
1234 connect(ram->pin_Q(idx), osig->pin(idx));
1235
1236 return osig;
1237 }
1238
1239 /*
1240 * Identifiers in continuous assignment l-values are limited to wires
1241 * and that ilk. Detect registers and memories here and report errors.
1242 */
1243 NetNet* PEIdent::elaborate_lnet(Design*des, const string&path) const
1244 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1245 NetScope*scope = des->find_scope(path);
1246 assert(scope);
1247
69612ce Move memories to the NetScope object.
steve authored
1248 NetNet*sig = des->find_signal(scope, text_);
a81dcd7 Support memories in continuous assignments.
steve authored
1249 if (sig == 0) {
1250 /* Don't allow memories here. Is it a memory? */
69612ce Move memories to the NetScope object.
steve authored
1251 if (des->find_memory(scope, text_)) {
a81dcd7 Support memories in continuous assignments.
steve authored
1252 cerr << get_line() << ": error: memories (" << text_
1253 << ") cannot be l-values in continuous "
1254 << "assignments." << endl;
1255 return 0;
1256 }
1257
1258 /* Fine, create an implicit wire as an l-value. */
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1259 sig = new NetNet(scope, path+"."+text_, NetNet::IMPLICIT, 1);
48de739 Switch to control warnings.
steve authored
1260
1261 if (warn_implicit)
1262 cerr << get_line() << ": warning: implicit "
1263 " definition of wire " << path << "." <<
1264 text_ << "." << endl;
a81dcd7 Support memories in continuous assignments.
steve authored
1265 }
1266
1267 assert(sig);
1268
1269 /* Don't allow registers as assign l-values. */
1270 if (sig->type() == NetNet::REG) {
1271 cerr << get_line() << ": error: registers (" << sig->name()
1272 << ") cannot be l-values in continuous"
1273 << " assignments." << endl;
1274 return 0;
1275 }
1276
1277 if (msb_ && lsb_) {
1278 /* Detect a part select. Evaluate the bits and elaborate
1279 the l-value by creating a sub-net that links to just
1280 the right pins. */
1281 verinum*mval = msb_->eval_const(des, path);
1282 assert(mval);
1283 verinum*lval = lsb_->eval_const(des, path);
1284 assert(lval);
1285 unsigned midx = sig->sb_to_idx(mval->as_long());
1286 unsigned lidx = sig->sb_to_idx(lval->as_long());
1287
1288 if (midx >= lidx) {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1289 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path),
a81dcd7 Support memories in continuous assignments.
steve authored
1290 midx-lidx+1);
1291 if (tmp->pin_count() > sig->pin_count()) {
1292 cerr << get_line() << ": bit select out of "
1293 << "range for " << sig->name() << endl;
1294 return sig;
1295 }
1296
1297 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1298 connect(tmp->pin(idx-lidx), sig->pin(idx));
1299
1300 sig = tmp;
1301
1302 } else {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1303 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path),
a81dcd7 Support memories in continuous assignments.
steve authored
1304 lidx-midx+1);
4eed86d Detect part select errors on l-values.
steve authored
1305
1306 if (tmp->pin_count() > sig->pin_count()) {
1307 cerr << get_line() << ": error: "
1308 << "part select out of range for "
1309 << sig->name() << "." << endl;
1310 des->errors += 1;
1311 return sig;
1312 }
1313
a81dcd7 Support memories in continuous assignments.
steve authored
1314 assert(tmp->pin_count() <= sig->pin_count());
1315 for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
1316 connect(tmp->pin(idx-midx), sig->pin(idx));
1317
1318 sig = tmp;
1319 }
1320
1321 } else if (msb_) {
1322 verinum*mval = msb_->eval_const(des, path);
1323 if (mval == 0) {
3ce86f5 Make error message include error: prefix.
steve authored
1324 cerr << get_line() << ": error: index of " << text_ <<
ac81f6a Rearrange NetAssign to make NetAssign_ separate.
steve authored
1325 " needs to be constant in l-value of assignment." <<
a81dcd7 Support memories in continuous assignments.
steve authored
1326 endl;
1327 des->errors += 1;
1328 return 0;
1329 }
1330 assert(mval);
1331 unsigned idx = sig->sb_to_idx(mval->as_long());
1332 if (idx >= sig->pin_count()) {
1333 cerr << get_line() << "; index " << sig->name() <<
1334 "[" << mval->as_long() << "] out of range." << endl;
1335 des->errors += 1;
1336 idx = 0;
1337 }
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1338 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path), 1);
a81dcd7 Support memories in continuous assignments.
steve authored
1339 connect(tmp->pin(0), sig->pin(idx));
1340 sig = tmp;
1341 }
1342
1343 return sig;
1344 }
1345
206b37e Fix NetConst being set to zero width, and clean
steve authored
1346 /*
3676d66 Module ports are really special PEIdent
steve authored
1347 * This method is used to elaborate identifiers that are ports to a
1348 * scope. The scope is presumed to be that of the module that has the
1349 * port.
1350 */
1351 NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
1352 {
1353 const string path = scope->name();
1354
1355 NetNet*sig = des->find_signal(scope, text_);
1356 if (sig == 0) {
1357 cerr << get_line() << ": error: no wire/reg " << text_
1358 << " in module " << scope->name() << "." << endl;
1359 des->errors += 1;
1360 return 0;
1361 }
1362
a59bbde Proper error messages when port direction is missing.
steve authored
1363 switch (sig->port_type()) {
1364 case NetNet::PINPUT:
1365 case NetNet::POUTPUT:
1366 case NetNet::PINOUT:
1367 break;
1368
1369 /* If the name matches, but the signal is not a port,
1370 then the user declared the object but there is no
1371 matching input/output/inout declaration. */
1372
1373 case NetNet::NOT_A_PORT:
1374 cerr << get_line() << ": error: signal " << text_ << " in"
1375 << " module " << scope->name() << " is not a port." << endl;
1376 cerr << get_line() << ": : Are you missing an input/"
1377 << "output/inout declaration?" << endl;
1378 des->errors += 1;
1379 return 0;
1380
1381 /* This should not happen. A PWire can only become
1382 PIMPLICIT if this is a udp reg port, and the make_udp
1383 function should turn it into an output.... I think. */
1384
1385 case NetNet::PIMPLICIT:
1386 cerr << get_line() << ": internal error: signal " << text_
1387 << " in module " << scope->name() << " is left as "
1388 << "port type PIMPLICIT." << endl;
1389 des->errors += 1;
1390 return 0;
1391 }
1392
3676d66 Module ports are really special PEIdent
steve authored
1393
1394 if (msb_ && lsb_) {
1395 /* Detect a part select. Evaluate the bits and elaborate
1396 the l-value by creating a sub-net that links to just
1397 the right pins. */
1398 verinum*mval = msb_->eval_const(des, path);
1399 assert(mval);
1400 verinum*lval = lsb_->eval_const(des, path);
1401 assert(lval);
1402 unsigned midx = sig->sb_to_idx(mval->as_long());
1403 unsigned lidx = sig->sb_to_idx(lval->as_long());
1404
1405 if (midx >= lidx) {
1406 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path),
1407 midx-lidx+1);
1408 if (tmp->pin_count() > sig->pin_count()) {
1409 cerr << get_line() << ": bit select out of "
1410 << "range for " << sig->name() << endl;
1411 return sig;
1412 }
1413
1414 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1415 connect(tmp->pin(idx-lidx), sig->pin(idx));
1416
1417 sig = tmp;
1418
1419 } else {
1420 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path),
1421 lidx-midx+1);
1422 assert(tmp->pin_count() <= sig->pin_count());
1423 for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
1424 connect(tmp->pin(idx-midx), sig->pin(idx));
1425
1426 sig = tmp;
1427 }
1428
1429 } else if (msb_) {
1430 verinum*mval = msb_->eval_const(des, path);
1431 if (mval == 0) {
1432 cerr << get_line() << ": index of " << text_ <<
ac81f6a Rearrange NetAssign to make NetAssign_ separate.
steve authored
1433 " needs to be constant in port context." <<
3676d66 Module ports are really special PEIdent
steve authored
1434 endl;
1435 des->errors += 1;
1436 return 0;
1437 }
1438 assert(mval);
1439 unsigned idx = sig->sb_to_idx(mval->as_long());
1440 if (idx >= sig->pin_count()) {
1441 cerr << get_line() << "; index " << sig->name() <<
1442 "[" << mval->as_long() << "] out of range." << endl;
1443 des->errors += 1;
1444 idx = 0;
1445 }
1446 NetTmp*tmp = new NetTmp(scope, des->local_symbol(path), 1);
1447 connect(tmp->pin(0), sig->pin(idx));
1448 sig = tmp;
1449 }
1450
1451 return sig;
1452 }
1453
1454
1455 /*
206b37e Fix NetConst being set to zero width, and clean
steve authored
1456 * Elaborate a number as a NetConst object.
1457 */
1458 NetNet* PENumber::elaborate_net(Design*des, const string&path,
1459 unsigned lwidth,
1460 unsigned long rise,
1461 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1462 unsigned long decay,
1463 Link::strength_t drive0,
1464 Link::strength_t drive1) const
206b37e Fix NetConst being set to zero width, and clean
steve authored
1465 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1466 NetScope*scope = des->find_scope(path);
1467 assert(scope);
1468
3d1ffce Elaborate net widths of constants to as small
steve authored
1469 /* If we are constrained by a l-value size, then just make a
1470 number constant with the correct size and set as many bits
1471 in that constant as make sense. Pad excess with zeros. */
1472 if (lwidth > 0) {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1473 NetNet*net = new NetNet(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
1474 NetNet::IMPLICIT, lwidth);
1475 net->local_flag(true);
1476
60c2046 Extend x or z that is top bit of a constant.
steve authored
1477 /* when expanding a constant to fit into the net, extend
1478 the Vx or Vz values if they are in the sign position,
1479 otherwise extend the number with 0 bits. */
1480 verinum::V top_v = verinum::V0;
1481 switch (value_->get(value_->len()-1)) {
1482 case verinum::Vx:
1483 top_v = verinum::Vx;
1484 break;
1485 case verinum::Vz:
1486 top_v = verinum::Vz;
1487 break;
1488 }
1489
1490 verinum num(top_v, net->pin_count());
3d1ffce Elaborate net widths of constants to as small
steve authored
1491 unsigned idx;
1492 for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
1493 num.set(idx, value_->get(idx));
1494
1495 NetConst*tmp = new NetConst(des->local_symbol(path), num);
b90cda1 Carry strength values from Verilog source to the
steve authored
1496 for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
1497 tmp->pin(idx).drive0(drive0);
1498 tmp->pin(idx).drive1(drive1);
3d1ffce Elaborate net widths of constants to as small
steve authored
1499 connect(net->pin(idx), tmp->pin(idx));
b90cda1 Carry strength values from Verilog source to the
steve authored
1500 }
3d1ffce Elaborate net widths of constants to as small
steve authored
1501
1502 des->add_node(tmp);
1503 return net;
1504 }
1505
1506 /* If the number has a length, then use that to size the
1507 number. Generate a constant object of exactly the user
1508 specified size. */
1509 if (value_->has_len()) {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1510 NetNet*net = new NetNet(scope, des->local_symbol(path),
3d1ffce Elaborate net widths of constants to as small
steve authored
1511 NetNet::IMPLICIT, value_->len());
1512 net->local_flag(true);
1513 NetConst*tmp = new NetConst(des->local_symbol(path), *value_);
1514 for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
1515 connect(net->pin(idx), tmp->pin(idx));
1516
1517 des->add_node(tmp);
1518 return net;
1519 }
1520
8ee00ec Fix net division to cope with small output sizes.
steve authored
1521 #if 0
1522 /* This warning is trying to catch the cases where an unsized
1523 integer in a netlist causes the netlist to explode in width
1524 even when it need not. This proved to be spurious and
1525 caused lots of false alarms, so it is commented out. */
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
1526 cerr << get_line() << ": warning: Number with indefinite size "
1527 << "in self-determined context." << endl;
8ee00ec Fix net division to cope with small output sizes.
steve authored
1528 #endif
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
1529
3d1ffce Elaborate net widths of constants to as small
steve authored
1530 /* None of the above tight constraints are present, so make a
1531 plausible choice for the width. Try to reduce the width as
1532 much as possible by eliminating high zeros of unsigned
1533 numbers. */
206b37e Fix NetConst being set to zero width, and clean
steve authored
1534 unsigned width = value_->len();
3d1ffce Elaborate net widths of constants to as small
steve authored
1535
1536 if (value_->has_sign() && (value_->get(width-1) == verinum::V0)) {
1537
1538 /* If the number is signed, but known to be positive,
1539 then reduce it down as if it were unsigned. */
1540 while (width > 1) {
1541 if (value_->get(width-1) != verinum::V0)
1542 break;
1543 width -= 1;
1544 }
1545
1546 } else if (value_->has_sign() == false) {
1547 while ( (width > 1) && (value_->get(width-1) == verinum::V0))
1548 width -= 1;
1549 }
1550
1551 verinum num (verinum::V0, width);
1552 for (unsigned idx = 0 ; idx < width ; idx += 1)
1553 num.set(idx, value_->get(idx));
206b37e Fix NetConst being set to zero width, and clean
steve authored
1554
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1555 NetNet*net = new NetNet(scope, des->local_symbol(path),
206b37e Fix NetConst being set to zero width, and clean
steve authored
1556 NetNet::IMPLICIT, width);
1557 net->local_flag(true);
3d1ffce Elaborate net widths of constants to as small
steve authored
1558 NetConst*tmp = new NetConst(des->local_symbol(path), num);
65ae928 NetConst can now hold wide constants.
steve authored
1559 for (unsigned idx = 0 ; idx < width ; idx += 1)
1560 connect(net->pin(idx), tmp->pin(idx));
206b37e Fix NetConst being set to zero width, and clean
steve authored
1561
65ae928 NetConst can now hold wide constants.
steve authored
1562 des->add_node(tmp);
206b37e Fix NetConst being set to zero width, and clean
steve authored
1563 return net;
1564 }
1565
1566
1567 /*
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1568 * Elaborate the ternary operator in a netlist by creating a LPM_MUX
0a70a8a Allow ternary result to be padded to result width.
steve authored
1569 * with width matching the result, size == 2 and 1 select input. These
1570 * expressions come from code like:
1571 *
1572 * res = test ? a : b;
1573 *
1574 * The res has the width requested of this method, and the a and b
1575 * expressions have their own similar widths. The test expression is
1576 * only a single bit wide. The output from this function is a NetNet
1577 * object the width of the <res> expression and connected to the
1578 * Result pins of the LPM_MUX device. Any width not covered by the
1579 * width of the mux is padded with a NetConst device.
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1580 */
1581 NetNet* PETernary::elaborate_net(Design*des, const string&path,
1582 unsigned width,
1583 unsigned long rise,
1584 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1585 unsigned long decay,
1586 Link::strength_t drive0,
1587 Link::strength_t drive1) const
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1588 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1589 NetScope*scope = des->find_scope(path);
1590 assert(scope);
1591
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1592 NetNet* expr_sig = expr_->elaborate_net(des, path, 0, 0, 0, 0);
1593 NetNet* tru_sig = tru_->elaborate_net(des, path, width, 0, 0, 0);
1594 NetNet* fal_sig = fal_->elaborate_net(des, path, width, 0, 0, 0);
1595 if (expr_sig == 0 || tru_sig == 0 || fal_sig == 0) {
1596 des->errors += 1;
1597 return 0;
1598 }
1599
44438c9 more robust abut ternary bit widths.
steve authored
1600
1601 /* The natural width of the expression is the width of the
1602 largest condition. Normally they should be the same size,
1603 but if we do not get a size from the context, or the
1604 expressions resist, we need to cope. */
1605 unsigned iwidth = tru_sig->pin_count();
1606 if (fal_sig->pin_count() > iwidth)
1607 iwidth = fal_sig->pin_count();
1608
1609
1610 /* If the width is not passed from the context, then take the
1611 widest result as our width. */
0a70a8a Allow ternary result to be padded to result width.
steve authored
1612 if (width == 0)
44438c9 more robust abut ternary bit widths.
steve authored
1613 width = iwidth;
0a70a8a Allow ternary result to be padded to result width.
steve authored
1614
e0dcdf6 Handle wide conditions in ternary operator.
steve authored
1615 /* If the expression has width, then generate a boolean result
1616 by connecting an OR gate to calculate the truth value of
44438c9 more robust abut ternary bit widths.
steve authored
1617 the result. In the end, the result needs to be a single bit. */
e0dcdf6 Handle wide conditions in ternary operator.
steve authored
1618 if (expr_sig->pin_count() > 1) {
76e2c50 Put logic devices into scopes.
steve authored
1619 NetLogic*log = new NetLogic(scope, des->local_symbol(path),
e0dcdf6 Handle wide conditions in ternary operator.
steve authored
1620 expr_sig->pin_count()+1,
1621 NetLogic::OR);
1622 for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1)
1623 connect(log->pin(idx+1), expr_sig->pin(idx));
1624
1625 NetNet*tmp = new NetTmp(scope, des->local_symbol(path));
1626 tmp->local_flag(true);
1627 connect(tmp->pin(0), log->pin(0));
1628 des->add_node(log);
1629
1630 expr_sig = tmp;
1631 }
1632
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1633 assert(expr_sig->pin_count() == 1);
1634
0a70a8a Allow ternary result to be padded to result width.
steve authored
1635 /* This is the width of the LPM_MUX device that I'm about to
1636 create. It may be smaller then the desired output, but I'll
1637 handle padding below.
1638
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1639 Create a NetNet object wide enough to hold the
1640 result. Also, pad the result values (if necessary) so that
1641 the mux inputs can be fully connected. */
0a70a8a Allow ternary result to be padded to result width.
steve authored
1642
44438c9 more robust abut ternary bit widths.
steve authored
1643 unsigned dwidth = (iwidth > width)? width : iwidth;
0a70a8a Allow ternary result to be padded to result width.
steve authored
1644
44438c9 more robust abut ternary bit widths.
steve authored
1645 NetNet*sig = new NetNet(scope, des->local_symbol(path),
1646 NetNet::WIRE, width);
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1647 sig->local_flag(true);
1648
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1649 if (fal_sig->pin_count() < dwidth)
2b0aaec FreeBSD port has a maintainer now.
steve authored
1650 fal_sig = pad_to_width(des, fal_sig, dwidth);
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1651
1652 if (tru_sig->pin_count() < dwidth)
2b0aaec FreeBSD port has a maintainer now.
steve authored
1653 tru_sig = pad_to_width(des, tru_sig, dwidth);
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1654
0a70a8a Allow ternary result to be padded to result width.
steve authored
1655
1656 /* Make the device and connect its outputs to the osig and
1657 inputs to the tru and false case nets. Also connect the
44438c9 more robust abut ternary bit widths.
steve authored
1658 selector bit to the sel input.
1659
1660 The inputs are the 0 (false) connected to fal_sig and 1
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1661 (true) connected to tru_sig. */
0a70a8a Allow ternary result to be padded to result width.
steve authored
1662
145ac49 NetMux needs a scope. (PR#115)
steve authored
1663 NetMux*mux = new NetMux(scope, des->local_symbol(path), dwidth, 2, 1);
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1664 connect(mux->pin_Sel(0), expr_sig->pin(0));
1665
0a70a8a Allow ternary result to be padded to result width.
steve authored
1666 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1667 connect(mux->pin_Result(idx), sig->pin(idx));
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1668 connect(mux->pin_Data(idx,0), fal_sig->pin(idx));
1669 connect(mux->pin_Data(idx,1), tru_sig->pin(idx));
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1670 }
5171846 Forgot to return the mux for use after elaboration.
steve authored
1671
44438c9 more robust abut ternary bit widths.
steve authored
1672
1673 /* If the MUX device result is too narrow to fill out the
1674 desired result, pad with zeros by creating a NetConst device. */
0a70a8a Allow ternary result to be padded to result width.
steve authored
1675
1676 if (dwidth < width) {
1677 verinum vpad (verinum::V0, width-dwidth);
ff514aa pad different width inputs to muxes. (PR#14)
steve authored
1678 NetConst*pad = new NetConst(des->local_symbol(path), vpad);
0a70a8a Allow ternary result to be padded to result width.
steve authored
1679 des->add_node(pad);
1680 for (unsigned idx = dwidth ; idx < width ; idx += 1)
1681 connect(sig->pin(idx), pad->pin(idx-dwidth));
1682 }
1683
5171846 Forgot to return the mux for use after elaboration.
steve authored
1684 des->add_node(mux);
1685
1686 return sig;
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
1687 }
1688
0d5e4b4 Structural reduction XNOR.
steve authored
1689 NetNet* PEUnary::elaborate_net(Design*des, const string&path,
1690 unsigned width,
1691 unsigned long rise,
1692 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1693 unsigned long decay,
1694 Link::strength_t drive0,
1695 Link::strength_t drive1) const
0d5e4b4 Structural reduction XNOR.
steve authored
1696 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1697 NetScope*scope = des->find_scope(path);
1698 assert(scope);
1699
4124273 Handle some special cases of unary 2's complement,
steve authored
1700 // Some unary operands allow the operand to be
1701 // self-determined, and some do not.
1702 unsigned owidth = 0;
1703 switch (op_) {
1704 case '~':
1705 case '-':
1706 owidth = width;
1707 break;
1708 }
1709
88a2ca2 Handle wide net constants with unary minus.
steve authored
1710 NetNet* sig;
1711 NetLogic*gate;
1712
1713 // Handle the special case of a 2's complement of a constant
1714 // value. This can be reduced to a no-op on a precalculated
1715 // result.
1716 if (op_ == '-') do {
1717 verinum*val = expr_->eval_const(des, path);
1718 if (val == 0)
1719 break;
1720
1721 sig = new NetNet(scope, des->local_symbol(path),
1722 NetNet::WIRE, width);
1723 sig->local_flag(true);
1724
1725 verinum tmp(v_not(*val) + verinum(1UL, width), width);
1726 NetConst*con = new NetConst(des->local_symbol(path), tmp);
1727 for (unsigned idx = 0 ; idx < width ; idx += 1)
1728 connect(sig->pin(idx), con->pin(idx));
1729
1730 des->add_node(con);
1731 return sig;
1732 } while (0);
1733
4124273 Handle some special cases of unary 2's complement,
steve authored
1734 NetNet* sub_sig = expr_->elaborate_net(des, path, owidth, 0, 0, 0);
0d5e4b4 Structural reduction XNOR.
steve authored
1735 if (sub_sig == 0) {
1736 des->errors += 1;
1737 return 0;
1738 }
1739 assert(sub_sig);
1740
1741 switch (op_) {
1742 case '~': // Bitwise NOT
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1743 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE,
0d5e4b4 Structural reduction XNOR.
steve authored
1744 sub_sig->pin_count());
1745 sig->local_flag(true);
1746 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1) {
76e2c50 Put logic devices into scopes.
steve authored
1747 gate = new NetLogic(scope, des->local_symbol(path),
1748 2, NetLogic::NOT);
0d5e4b4 Structural reduction XNOR.
steve authored
1749 connect(gate->pin(1), sub_sig->pin(idx));
1750 connect(gate->pin(0), sig->pin(idx));
1751 des->add_node(gate);
1752 gate->rise_time(rise);
1753 gate->fall_time(fall);
1754 gate->decay_time(decay);
1755 }
1756 break;
1757
1758 case 'N': // Reduction NOR
1759 case '!': // Reduction NOT
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1760 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
0d5e4b4 Structural reduction XNOR.
steve authored
1761 sig->local_flag(true);
76e2c50 Put logic devices into scopes.
steve authored
1762 gate = new NetLogic(scope, des->local_symbol(path),
1763 1+sub_sig->pin_count(), NetLogic::NOR);
0d5e4b4 Structural reduction XNOR.
steve authored
1764 connect(gate->pin(0), sig->pin(0));
1765 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
1766 connect(gate->pin(idx+1), sub_sig->pin(idx));
1767
1768 des->add_node(gate);
1769 gate->rise_time(rise);
1770 gate->fall_time(fall);
1771 gate->decay_time(decay);
1772 break;
1773
1774 case '&': // Reduction AND
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1775 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
0d5e4b4 Structural reduction XNOR.
steve authored
1776 sig->local_flag(true);
76e2c50 Put logic devices into scopes.
steve authored
1777 gate = new NetLogic(scope, des->local_symbol(path),
1778 1+sub_sig->pin_count(), NetLogic::AND);
0d5e4b4 Structural reduction XNOR.
steve authored
1779 connect(gate->pin(0), sig->pin(0));
1780 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
1781 connect(gate->pin(idx+1), sub_sig->pin(idx));
1782
1783 des->add_node(gate);
1784 gate->rise_time(rise);
1785 gate->fall_time(fall);
1786 gate->decay_time(decay);
1787 break;
1788
1789 case '|': // Reduction OR
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1790 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
0d5e4b4 Structural reduction XNOR.
steve authored
1791 sig->local_flag(true);
76e2c50 Put logic devices into scopes.
steve authored
1792 gate = new NetLogic(scope, des->local_symbol(path),
1793 1+sub_sig->pin_count(), NetLogic::OR);
0d5e4b4 Structural reduction XNOR.
steve authored
1794 connect(gate->pin(0), sig->pin(0));
1795 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
1796 connect(gate->pin(idx+1), sub_sig->pin(idx));
1797
1798 des->add_node(gate);
1799 gate->rise_time(rise);
1800 gate->fall_time(fall);
1801 gate->decay_time(decay);
1802 break;
1803
1804 case '^': // Reduction XOR
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1805 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
0d5e4b4 Structural reduction XNOR.
steve authored
1806 sig->local_flag(true);
76e2c50 Put logic devices into scopes.
steve authored
1807 gate = new NetLogic(scope, des->local_symbol(path),
1808 1+sub_sig->pin_count(), NetLogic::XOR);
0d5e4b4 Structural reduction XNOR.
steve authored
1809 connect(gate->pin(0), sig->pin(0));
1810 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
1811 connect(gate->pin(idx+1), sub_sig->pin(idx));
1812
1813 des->add_node(gate);
1814 gate->rise_time(rise);
1815 gate->fall_time(fall);
1816 gate->decay_time(decay);
1817 break;
1818
9e5ff89 Add structural reduction NAND,
steve authored
1819 case 'A': // Reduction NAND (~&)
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1820 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
9e5ff89 Add structural reduction NAND,
steve authored
1821 sig->local_flag(true);
76e2c50 Put logic devices into scopes.
steve authored
1822 gate = new NetLogic(scope, des->local_symbol(path),
1823 1+sub_sig->pin_count(), NetLogic::NAND);
9e5ff89 Add structural reduction NAND,
steve authored
1824 connect(gate->pin(0), sig->pin(0));
1825 for (unsigned idx = 0 ; idx < sub_sig->pin_count() ; idx += 1)
1826 connect(gate->pin(idx+1), sub_sig->pin(idx));
1827
1828 des->add_node(gate);
1829 gate->rise_time(rise);
1830 gate->fall_time(fall);
1831 gate->decay_time(decay);
1832 break;
1833
1834
1835 case 'X': // Reduction XNOR (~^)
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1836 sig = new NetNet(scope, des->local_symbol(path), NetNet::WIRE);
0d5e4b4 Structural reduction XNOR.
steve authored
1837 sig->local_flag(true);