Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 2674 lines (2275 sloc) 80.919 kB
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
1 /*
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
2 * Copyright (c) 1999-2004 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 */
52bf4e6 conditional ident string using autoconfig.
steve authored
19 #ifdef HAVE_CVS_IDENT
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
20 #ident "$Id: elab_net.cc,v 1.140 2005/01/09 20:16:00 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
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
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
03aebd7 Support elaborate_net for PEString objects.
steve authored
41 NetNet* PExpr::elaborate_net(Design*des, NetScope*scope, unsigned,
42 unsigned long,
43 unsigned long,
44 unsigned long,
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
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
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 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
58 NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
59 unsigned width,
60 unsigned long rise,
61 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
62 unsigned long decay,
63 Link::strength_t drive0,
64 Link::strength_t drive1) const
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
65 {
66 switch (op_) {
aa8908c Multiplication all the way to simulation.
steve authored
67 case '*':
7793a49 Remove string paths from PExpr elaboration.
steve authored
68 return elaborate_net_mul_(des, scope, width, rise, fall, decay);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
69 case '%':
7793a49 Remove string paths from PExpr elaboration.
steve authored
70 return elaborate_net_mod_(des, scope, width, rise, fall, decay);
694ff93 Add support for integer division.
steve authored
71 case '/':
7793a49 Remove string paths from PExpr elaboration.
steve authored
72 return elaborate_net_div_(des, scope, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
73 case '+':
74 case '-':
7793a49 Remove string paths from PExpr elaboration.
steve authored
75 return elaborate_net_add_(des, scope, width, rise, fall, decay);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
76 case '|': // Bitwise OR
77 case '&':
78 case '^':
dac99b9 Add support for binary nand operator.
steve authored
79 case 'A': // Bitwise NAND (~&)
3d3116d Add support for binary NOR operator.
steve authored
80 case 'O': // Bitwise NOR (~|)
8f0c02c Spelling fixes.
steve authored
81 case 'X': // Exclusive NOR
7793a49 Remove string paths from PExpr elaboration.
steve authored
82 return elaborate_net_bit_(des, scope, width, rise, fall, decay);
b8c5aff Generate !== an an inverted ===
steve authored
83 case 'E': // === (case equals)
84 case 'e': // ==
85 case 'N': // !== (case not-equals)
86 case 'n': // !=
513ade9 Support combinatorial comparators.
steve authored
87 case '<':
88 case '>':
89 case 'L': // <=
90 case 'G': // >=
7793a49 Remove string paths from PExpr elaboration.
steve authored
91 return elaborate_net_cmp_(des, scope, width, rise, fall, decay);
ced7cc6 Structural logical or.
steve authored
92 case 'a': // && (logical and)
93 case 'o': // || (logical or)
7793a49 Remove string paths from PExpr elaboration.
steve authored
94 return elaborate_net_log_(des, scope, width, rise, fall, decay);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
95 case 'l': // <<
96 case 'r': // >>
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
97 case 'R': // >>>
7793a49 Remove string paths from PExpr elaboration.
steve authored
98 return elaborate_net_shift_(des, scope, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
99 }
100
7793a49 Remove string paths from PExpr elaboration.
steve authored
101 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
102 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
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
57d28e4 Support structural XNOR.
steve authored
120 case 'X': // XNOR
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
121 case '&': // AND
122 case '|': // Bitwise OR
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
123 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
124 break;
125
126 case 'E': // === (Case equals)
127 case 'e': // ==
128 case 'n': // !=
513ade9 Support combinatorial comparators.
steve authored
129 case '<':
130 case '>':
131 case 'G': // >=
132 case 'L': // <=
206b37e Fix NetConst being set to zero width, and clean
steve authored
133 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
134 break;
135
136 case '+':
137 assert(0);
138 break;
139
140 case 'l':
141 case 'r':
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
142 case 'R':
1624afe Add support for the LPM_CLSHIFT device.
steve authored
143 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
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
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
152 if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(lsig))
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
153 delete tmp;
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
154 if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(rsig))
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
155 delete tmp;
156
157 return osig;
158 }
159
160 /*
161 * Elaborate the structural +/- as an AddSub object. Connect DataA and
162 * DataB to the parameters, and connect the output signal to the
163 * Result. In this context, the device is a combinational adder with
164 * fixed direction, so leave Add_Sub unconnected and set the
165 * LPM_Direction property.
166 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
167 NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
168 unsigned lwidth,
169 unsigned long rise,
170 unsigned long fall,
171 unsigned long decay) const
172 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
173 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
174 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
175 if (lsig == 0) {
176 cerr << get_line() << ": error: Cannot elaborate ";
177 left_->dump(cerr);
178 cerr << endl;
179 return 0;
180 }
181 if (rsig == 0) {
182 cerr << get_line() << ": error: Cannot elaborate ";
183 right_->dump(cerr);
184 cerr << endl;
185 return 0;
186 }
187
188 NetNet*osig;
189
190 unsigned width = lsig->pin_count();
191 if (rsig->pin_count() > lsig->pin_count())
192 width = rsig->pin_count();
193
d78c739 Remove dead code.
steve authored
194
4124273 Handle some special cases of unary 2's complement,
steve authored
195 /* The owidth is the output width of the lpm_add_sub
7c1401a Spelling patch.
steve authored
196 device. If the desired width is greater then the width of
4124273 Handle some special cases of unary 2's complement,
steve authored
197 the operands, then widen the adder and let code below pad
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
198 the operands. */
4124273 Handle some special cases of unary 2's complement,
steve authored
199 unsigned owidth = width;
200 switch (op_) {
201 case '+':
202 if (lwidth > owidth) {
203 owidth = lwidth;
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
204 width = lwidth;
4124273 Handle some special cases of unary 2's complement,
steve authored
205 }
206 break;
207 case '-':
208 if (lwidth > owidth) {
209 owidth = lwidth;
210 width = lwidth;
211 }
212 break;
213 default:
214 assert(0);
215 }
d78c739 Remove dead code.
steve authored
216
d54cc14 Simulate carry output on adders.
steve authored
217
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
218 // Pad out the operands, if necessary, the match the width of
219 // the adder device.
220 if (lsig->pin_count() < width)
2b0aaec FreeBSD port has a maintainer now.
steve authored
221 lsig = pad_to_width(des, lsig, width);
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
222
223 if (rsig->pin_count() < width)
2b0aaec FreeBSD port has a maintainer now.
steve authored
224 rsig = pad_to_width(des, rsig, width);
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
225
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
226 // Make the adder as wide as the widest operand
badad63 All NetObj objects have lex_string base names.
steve authored
227 osig = new NetNet(scope, scope->local_symbol(),
4124273 Handle some special cases of unary 2's complement,
steve authored
228 NetNet::WIRE, owidth);
229 osig->local_flag(true);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
230 if (debug_elaborate) {
231 cerr << get_line() << ": debug: Elaborate NetAddSub "
232 << "width=" << width << " lwidth=" << lwidth
233 << endl;
234 }
badad63 All NetObj objects have lex_string base names.
steve authored
235 NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
236
237 // Connect the adder to the various parts.
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
238 connect(lsig->pin(0), adder->pin_DataA());
239 connect(rsig->pin(0), adder->pin_DataB());
240 connect(osig->pin(0), adder->pin_Result());
241 #ifdef XXXX
d54cc14 Simulate carry output on adders.
steve authored
242 if (owidth > width)
243 connect(osig->pin(width), adder->pin_Cout());
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
244 #endif
61195c5 Harmless fixup of warnings.
steve authored
245 NetNode*gate = adder;
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
246 gate->rise_time(rise);
247 gate->fall_time(fall);
248 gate->decay_time(decay);
249 des->add_node(gate);
250
9ee0210 Code cleanup from Larry.
steve authored
251 gate->attribute(perm_string::literal("LPM_Direction"),
252 verinum(op_ == '+' ? "ADD" : "SUB"));
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
253
254 return osig;
255 }
256
257 /*
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
258 * Elaborate various bitwise logic operators. These are all similar in
259 * that they take operants of equal width, and each bit does not
260 * affect any other bits. Also common about all this is how bit widths
261 * of the operands are handled, when they do not match.
262 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
263 NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
264 unsigned width,
265 unsigned long rise,
266 unsigned long fall,
267 unsigned long decay) const
268 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
269 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
270 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
271 if (lsig == 0) {
272 cerr << get_line() << ": error: Cannot elaborate ";
273 left_->dump(cerr);
274 cerr << endl;
275 return 0;
276 }
277 if (rsig == 0) {
278 cerr << get_line() << ": error: Cannot elaborate ";
279 right_->dump(cerr);
280 cerr << endl;
281 return 0;
282 }
283
284 if (lsig->pin_count() < rsig->pin_count())
2b0aaec FreeBSD port has a maintainer now.
steve authored
285 lsig = pad_to_width(des, lsig, rsig->pin_count());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
286 if (rsig->pin_count() < lsig->pin_count())
2b0aaec FreeBSD port has a maintainer now.
steve authored
287 rsig = pad_to_width(des, rsig, lsig->pin_count());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
288
289 if (lsig->pin_count() != rsig->pin_count()) {
290 cerr << get_line() << ": internal error: lsig pin count ("
291 << lsig->pin_count() << ") != rsig pin count ("
292 << rsig->pin_count() << ")." << endl;
293 des->errors += 1;
294 return 0;
295 }
296
297 assert(lsig->pin_count() == rsig->pin_count());
298
badad63 All NetObj objects have lex_string base names.
steve authored
299 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE,
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
300 lsig->pin_count());
301 osig->local_flag(true);
302
9ee0210 Code cleanup from Larry.
steve authored
303 NetLogic::TYPE gtype=NetLogic::AND;
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
304 switch (op_) {
9ee0210 Code cleanup from Larry.
steve authored
305 case '^': gtype = NetLogic::XOR; break; // XOR
306 case 'X': gtype = NetLogic::XNOR; break; // XNOR
307 case '&': gtype = NetLogic::AND; break; // AND
308 case 'A': gtype = NetLogic::NAND; break; // NAND (~&)
309 case '|': gtype = NetLogic::OR; break; // Bitwise OR
310 case 'O': gtype = NetLogic::NOR; break; // Bitwise NOR
311 default: assert(0);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
312 }
313
9ee0210 Code cleanup from Larry.
steve authored
314 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
315 NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
316 3, gtype, 1);
9ee0210 Code cleanup from Larry.
steve authored
317 connect(gate->pin(1), lsig->pin(idx));
318 connect(gate->pin(2), rsig->pin(idx));
319 connect(gate->pin(0), osig->pin(idx));
320 gate->rise_time(rise);
321 gate->fall_time(fall);
322 gate->decay_time(decay);
323 des->add_node(gate);
324 }
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
325
326 return osig;
327 }
328
329 /*
fd371a3 Handle equality compare to constants specially.
steve authored
330 * This function attempts to handle the special case of == or !=
331 * compare to a constant value. The caller has determined already that
332 * one of the operands is a NetEConst, and has already elaborated the
333 * other.
334 */
335 static NetNet* compare_eq_constant(Design*des, NetScope*scope,
336 NetNet*lsig, NetEConst*rexp,
337 char op_code,
338 unsigned long rise,
339 unsigned long fall,
340 unsigned long decay)
341 {
342 if (op_code != 'e' && op_code != 'n')
343 return 0;
344
345 verinum val = rexp->value();
346
347 /* Abandon special case if there are x or z bits in the
348 constant. We can't get the right behavior out of
349 OR/NOR in this case. */
350 if (! val.is_defined())
351 return 0;
352
353 if (val.len() < lsig->pin_count())
354 val = verinum(val, lsig->pin_count());
355
03d7448 compare-to-constant uses sig len, not val len.
steve authored
356 /* Look for the very special case that we know the compare
357 results a priori due to different high bits, that are
358 constant pad in the signal. */
359 if (val.len() > lsig->pin_count()) {
360 unsigned idx = lsig->pin_count();
361 verinum::V lpad = verinum::V0;
362
363 while (idx < val.len()) {
364 if (val.get(idx) != lpad) {
365 verinum oval (op_code == 'e'
366 ? verinum::V0
367 : verinum::V1,
368 1);
369 NetEConst*ogate = new NetEConst(oval);
370 NetNet*osig = ogate->synthesize(des);
371 delete ogate;
372 return osig;
373 }
374
375 idx +=1;
376 }
377 }
fd371a3 Handle equality compare to constants specially.
steve authored
378
379 unsigned zeros = 0;
380 unsigned ones = 0;
03d7448 compare-to-constant uses sig len, not val len.
steve authored
381 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
fd371a3 Handle equality compare to constants specially.
steve authored
382 if (val.get(idx) == verinum::V0)
383 zeros += 1;
384 if (val.get(idx) == verinum::V1)
385 ones += 1;
386 }
387
69cfdbd Fix broken calcuation of NE for constant.
steve authored
388 /* Now make reduction logic to test that all the 1 bits are 1,
389 and all the 0 bits are 0. The results will be ANDed
390 together later, if needed. NOTE that if the compare is !=,
391 and we know that we will not need an AND later, then fold
392 the final invert into the reduction gate to get the right
393 sense of the output. If we do need the AND later, then we
394 will put the invert on that instead. */
fd371a3 Handle equality compare to constants specially.
steve authored
395 NetLogic*zero_gate = 0;
396 NetLogic*ones_gate = 0;
9ee0210 Code cleanup from Larry.
steve authored
397 if (zeros > 0)
398 zero_gate = new NetLogic(scope,
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
399 scope->local_symbol(), zeros + 1,
400 (op_code == 'n') ? NetLogic::OR : NetLogic::NOR, 1);
9ee0210 Code cleanup from Larry.
steve authored
401 if (ones > 0)
402 ones_gate = new NetLogic(scope,
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
403 scope->local_symbol(), ones + 1,
404 (op_code == 'n') ? NetLogic::NAND : NetLogic::AND, 1);
fd371a3 Handle equality compare to constants specially.
steve authored
405
406 unsigned zidx = 0;
407 unsigned oidx = 0;
03d7448 compare-to-constant uses sig len, not val len.
steve authored
408 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
fd371a3 Handle equality compare to constants specially.
steve authored
409 if (val.get(idx) == verinum::V0) {
410 zidx += 1;
411 connect(zero_gate->pin(zidx), lsig->pin(idx));
412 }
413 if (val.get(idx) == verinum::V1) {
414 oidx += 1;
415 connect(ones_gate->pin(oidx), lsig->pin(idx));
416 }
417 }
418
419 NetNet*osig = new NetNet(scope, scope->local_symbol(),
420 NetNet::WIRE, 1);
421 osig->local_flag(true);
422
423 if (zero_gate && ones_gate) {
424 NetNet*and_sig = new NetNet(scope, scope->local_symbol(),
425 NetNet::WIRE, 2);
426 and_sig->local_flag(true);
427 connect(and_sig->pin(0), zero_gate->pin(0));
428 connect(and_sig->pin(1), ones_gate->pin(0));
429 NetLogic*and_gate = new NetLogic(scope,
9ee0210 Code cleanup from Larry.
steve authored
430 scope->local_symbol(), 3,
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
431 (op_code == 'n') ? NetLogic::OR : NetLogic::AND, 1);
fd371a3 Handle equality compare to constants specially.
steve authored
432 connect(and_gate->pin(0), osig->pin(0));
433 connect(and_gate->pin(1), and_sig->pin(0));
434 connect(and_gate->pin(2), and_sig->pin(1));
435
436 des->add_node(and_gate);
437 des->add_node(zero_gate);
438 des->add_node(ones_gate);
439
440 } else if (zero_gate) {
441 connect(zero_gate->pin(0), osig->pin(0));
442 des->add_node(zero_gate);
443 } else {
444 assert(ones_gate);
445 connect(ones_gate->pin(0), osig->pin(0));
446 des->add_node(ones_gate);
447 }
448
449 return osig;
450 }
451
452 /*
3d1ffce Elaborate net widths of constants to as small
steve authored
453 * Elaborate the various binary comparison operators. The comparison
454 * operators return a single bit result, no matter what, so the left
455 * and right values can have their own size. The only restriction is
456 * that they have the same size.
206b37e Fix NetConst being set to zero width, and clean
steve authored
457 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
458 NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
206b37e Fix NetConst being set to zero width, and clean
steve authored
459 unsigned lwidth,
460 unsigned long rise,
461 unsigned long fall,
462 unsigned long decay) const
463 {
2f8a40b Fix evaluation of compare to constant expression.
steve authored
464 /* Elaborate the operands of the compare first as expressions
465 (so that the eval_tree method can reduce constant
466 expressions, including parameters) then turn those results
467 into synthesized nets. */
468 NetExpr*lexp = left_->elaborate_expr(des, scope);
469 if (lexp == 0) {
206b37e Fix NetConst being set to zero width, and clean
steve authored
470 cerr << get_line() << ": error: Cannot elaborate ";
471 left_->dump(cerr);
472 cerr << endl;
473 return 0;
474 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
475
476 if (NetExpr*tmp = lexp->eval_tree()) {
477 delete lexp;
478 lexp = tmp;
479 }
480
481 NetExpr*rexp = right_->elaborate_expr(des, scope);
482 if (rexp == 0) {
206b37e Fix NetConst being set to zero width, and clean
steve authored
483 cerr << get_line() << ": error: Cannot elaborate ";
484 right_->dump(cerr);
485 cerr << endl;
486 return 0;
487 }
488
2f8a40b Fix evaluation of compare to constant expression.
steve authored
489 if (NetExpr*tmp = rexp->eval_tree()) {
490 delete rexp;
491 rexp = tmp;
492 }
493
fd371a3 Handle equality compare to constants specially.
steve authored
494 NetNet*lsig = 0;
495 NetNet*rsig = 0;
496
497 /* Handle the special case that the right or left
498 sub-expression is a constant value. The compare_eq_constant
499 function will return an elaborated result if it can make
500 use of the situation, or 0 if it cannot. */
501 if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
502
503 lsig = lexp->synthesize(des);
51dd41f Fix excessive error message.
steve authored
504 if (lsig == 0) {
505 cerr << get_line() << ": internal error: "
506 "Cannot elaborate net for " << *lexp << endl;
507 }
fd371a3 Handle equality compare to constants specially.
steve authored
508 assert(lsig);
509 delete lexp;
510 lexp = 0;
511
512 NetNet*osig = compare_eq_constant(des, scope,
513 lsig, tmp, op_,
514 rise, fall, decay);
515 if (osig != 0) {
516 delete rexp;
517 return osig;
518 }
519 }
520
521 if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
522
523 rsig = rexp->synthesize(des);
524 assert(rsig);
525 delete rexp;
526
527 NetNet*osig = compare_eq_constant(des, scope,
528 rsig, tmp, op_,
529 rise, fall, decay);
530 if (osig != 0) {
531 delete lexp;
532 return osig;
533 }
534 }
535
536 if (lsig == 0) {
537 lsig = lexp->synthesize(des);
538 assert(lsig);
539 delete lexp;
540 }
541
542 if (rsig == 0) {
543 rsig = rexp->synthesize(des);
544 assert(rsig);
545 delete rexp;
546 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
547
3d1ffce Elaborate net widths of constants to as small
steve authored
548 unsigned dwidth = lsig->pin_count();
549 if (rsig->pin_count() > dwidth) dwidth = rsig->pin_count();
550
5d1d99a Handle signed magnitude compare all the
steve authored
551 /* Operands of binary compare need to be padded to equal
552 size. Figure the pad bit needed to extend the narrowest
553 vector. */
554 NetNet*padbit = 0;
3d1ffce Elaborate net widths of constants to as small
steve authored
555 if (lsig->pin_count() != rsig->pin_count()) {
5d1d99a Handle signed magnitude compare all the
steve authored
556 unsigned lwid = lsig->pin_count();
557 unsigned rwid = rsig->pin_count();
558
559 padbit = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
560 padbit->local_flag(true);
561
562 if (lsig->get_signed() && (lwid < rwid)) {
563
564 connect(padbit->pin(0), lsig->pin(lwid-1));
565
566 } else if (rsig->get_signed() && (rwid < lwid)) {
567
568 connect(padbit->pin(0), rsig->pin(rwid-1));
569
570 } else {
571 NetConst*tmp = new NetConst(scope, scope->local_symbol(),
572 verinum::V0);
573 des->add_node(tmp);
574 connect(tmp->pin(0), padbit->pin(0));
575 }
3d1ffce Elaborate net widths of constants to as small
steve authored
576 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
577
badad63 All NetObj objects have lex_string base names.
steve authored
578 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
206b37e Fix NetConst being set to zero width, and clean
steve authored
579 osig->local_flag(true);
580
581 NetNode*gate;
3d1ffce Elaborate net widths of constants to as small
steve authored
582 //NetNode*gate_t;
206b37e Fix NetConst being set to zero width, and clean
steve authored
583
584 switch (op_) {
513ade9 Support combinatorial comparators.
steve authored
585 case '<':
586 case '>':
587 case 'L':
588 case 'G': {
3d1ffce Elaborate net widths of constants to as small
steve authored
589 NetCompare*cmp = new
a275133 LPM objects store only their base names.
steve authored
590 NetCompare(scope, scope->local_symbol(), dwidth);
3d1ffce Elaborate net widths of constants to as small
steve authored
591 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
513ade9 Support combinatorial comparators.
steve authored
592 connect(cmp->pin_DataA(idx), lsig->pin(idx));
3d1ffce Elaborate net widths of constants to as small
steve authored
593 for (unsigned idx = lsig->pin_count(); idx < dwidth ; idx += 1)
5d1d99a Handle signed magnitude compare all the
steve authored
594 connect(cmp->pin_DataA(idx), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
595 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
513ade9 Support combinatorial comparators.
steve authored
596 connect(cmp->pin_DataB(idx), rsig->pin(idx));
3d1ffce Elaborate net widths of constants to as small
steve authored
597 for (unsigned idx = rsig->pin_count(); idx < dwidth ; idx += 1)
5d1d99a Handle signed magnitude compare all the
steve authored
598 connect(cmp->pin_DataB(idx), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
599
513ade9 Support combinatorial comparators.
steve authored
600 switch (op_) {
601 case '<':
602 connect(cmp->pin_ALB(), osig->pin(0));
603 break;
604 case '>':
605 connect(cmp->pin_AGB(), osig->pin(0));
606 break;
607 case 'L':
608 connect(cmp->pin_ALEB(), osig->pin(0));
609 break;
610 case 'G':
611 connect(cmp->pin_AGEB(), osig->pin(0));
612 break;
613 }
5d1d99a Handle signed magnitude compare all the
steve authored
614 /* If both operands are signed, then do a signed
615 compare. */
616 if (lsig->get_signed() && rsig->get_signed())
617 cmp->set_signed(true);
618
513ade9 Support combinatorial comparators.
steve authored
619 gate = cmp;
620 break;
621 }
622
206b37e Fix NetConst being set to zero width, and clean
steve authored
623 case 'E': // Case equals (===)
b8c5aff Generate !== an an inverted ===
steve authored
624 case 'N': // Case equals (!==)
206b37e Fix NetConst being set to zero width, and clean
steve authored
625 // The comparison generates gates to bitwise compare
626 // each pair, and AND all the comparison results.
b8c5aff Generate !== an an inverted ===
steve authored
627
badad63 All NetObj objects have lex_string base names.
steve authored
628 gate = new NetLogic(scope, scope->local_symbol(),
f224ed3 Fix out-of-bound pins for comparator (PR#108)
steve authored
629 1+dwidth,
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
630 (op_ == 'E')? NetLogic::AND : NetLogic::NAND, 1);
206b37e Fix NetConst being set to zero width, and clean
steve authored
631 connect(gate->pin(0), osig->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
632 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
874bab1 NetObj constructor finally requires a scope.
steve authored
633 NetCaseCmp*cmp = new NetCaseCmp(scope,
badad63 All NetObj objects have lex_string base names.
steve authored
634 scope->local_symbol());
3d1ffce Elaborate net widths of constants to as small
steve authored
635
636 if (idx < lsig->pin_count())
637 connect(cmp->pin(1), lsig->pin(idx));
638 else
5d1d99a Handle signed magnitude compare all the
steve authored
639 connect(cmp->pin(1), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
640
641 if (idx < rsig->pin_count())
642 connect(cmp->pin(2), rsig->pin(idx));
643 else
5d1d99a Handle signed magnitude compare all the
steve authored
644 connect(cmp->pin(2), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
645
646 connect(cmp->pin(0), gate->pin(idx+1));
647 des->add_node(cmp);
206b37e Fix NetConst being set to zero width, and clean
steve authored
648
649 // Attach a label to this intermediate wire
badad63 All NetObj objects have lex_string base names.
steve authored
650 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
206b37e Fix NetConst being set to zero width, and clean
steve authored
651 NetNet::WIRE);
652 tmp->local_flag(true);
3d1ffce Elaborate net widths of constants to as small
steve authored
653 connect(cmp->pin(0), tmp->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
654 }
655 break;
656
657
658 case 'e': // ==
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
659
660 /* Handle the special case of single bit compare with a
661 single XNOR gate. This is easy and direct. */
662 if (dwidth == 1) {
badad63 All NetObj objects have lex_string base names.
steve authored
663 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
664 3, NetLogic::XNOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
665 connect(gate->pin(0), osig->pin(0));
666 connect(gate->pin(1), lsig->pin(0));
667 connect(gate->pin(2), rsig->pin(0));
668 break;
669 }
670
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
671 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
672 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
673 dwidth);
674 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
3d1ffce Elaborate net widths of constants to as small
steve authored
675
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
676 if (idx < lsig->pin_count())
677 connect(cmp->pin_DataA(idx), lsig->pin(idx));
678 else
5d1d99a Handle signed magnitude compare all the
steve authored
679 connect(cmp->pin_DataA(idx), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
680
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
681 if (idx < rsig->pin_count())
682 connect(cmp->pin_DataB(idx), rsig->pin(idx));
683 else
5d1d99a Handle signed magnitude compare all the
steve authored
684 connect(cmp->pin_DataB(idx), padbit->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
685
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
686 }
687 connect(cmp->pin_AEB(), osig->pin(0));
688 gate = cmp;
206b37e Fix NetConst being set to zero width, and clean
steve authored
689 }
690 break;
691
692 case 'n': // !=
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
693
694 /* Handle the special case of single bit compare with a
695 single XOR gate. This is easy and direct. */
696 if (dwidth == 1) {
badad63 All NetObj objects have lex_string base names.
steve authored
697 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
698 3, NetLogic::XOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
699 connect(gate->pin(0), osig->pin(0));
700 connect(gate->pin(1), lsig->pin(0));
701 connect(gate->pin(2), rsig->pin(0));
702 break;
703 }
704
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
705 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
706 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
707 dwidth);
708 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
709
710 if (idx < lsig->pin_count())
711 connect(cmp->pin_DataA(idx), lsig->pin(idx));
712 else
5d1d99a Handle signed magnitude compare all the
steve authored
713 connect(cmp->pin_DataA(idx), padbit->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
714
715 if (idx < rsig->pin_count())
716 connect(cmp->pin_DataB(idx), rsig->pin(idx));
717 else
5d1d99a Handle signed magnitude compare all the
steve authored
718 connect(cmp->pin_DataB(idx), padbit->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
719
720 }
721 connect(cmp->pin_ANEB(), osig->pin(0));
722 gate = cmp;
723 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
724 break;
725
726 default:
727 assert(0);
728 }
729
730 gate->rise_time(rise);
731 gate->fall_time(fall);
732 gate->decay_time(decay);
733 des->add_node(gate);
734
735 return osig;
736 }
737
694ff93 Add support for integer division.
steve authored
738 /*
8f0c02c Spelling fixes.
steve authored
739 * Elaborate a divider gate. This function create a NetDivide gate
8ee00ec Fix net division to cope with small output sizes.
steve authored
740 * which has exactly the right sized DataA, DataB and Result ports. If
741 * the l-value is wider then the result, then pad.
694ff93 Add support for integer division.
steve authored
742 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
743 NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
694ff93 Add support for integer division.
steve authored
744 unsigned lwidth,
745 unsigned long rise,
746 unsigned long fall,
747 unsigned long decay) const
748 {
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
749 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
694ff93 Add support for integer division.
steve authored
750 if (lsig == 0) return 0;
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
751 NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
694ff93 Add support for integer division.
steve authored
752 if (rsig == 0) return 0;
753
8ee00ec Fix net division to cope with small output sizes.
steve authored
754
755 // Check the l-value width. If it is unspecified, then use the
756 // largest operand width as the l-value width. Restrict the
757 // result width to the width of the largest operand, because
758 // there is no value is excess divider.
759
760 unsigned rwidth = lwidth;
761
762 if (rwidth == 0) {
763 rwidth = lsig->pin_count();
764 if (rsig->pin_count() > rwidth)
765 rwidth = rsig->pin_count();
766
767 lwidth = rwidth;
768 }
769
770 if ((rwidth > lsig->pin_count()) && (rwidth > rsig->pin_count())) {
771 rwidth = lsig->pin_count();
772 if (rsig->pin_count() > rwidth)
773 rwidth = rsig->pin_count();
774 }
775
776 // Create a device with the calculated dimensions.
a275133 LPM objects store only their base names.
steve authored
777 NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth,
694ff93 Add support for integer division.
steve authored
778 lsig->pin_count(),
779 rsig->pin_count());
780 des->add_node(div);
781
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
782 div->set_signed(lsig->get_signed() && rsig->get_signed());
8ee00ec Fix net division to cope with small output sizes.
steve authored
783
784 // Connect the left and right inputs of the divider to the
785 // nets that are the left and right expressions.
786
694ff93 Add support for integer division.
steve authored
787 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
788 connect(div->pin_DataA(idx), lsig->pin(idx));
789 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
790 connect(div->pin_DataB(idx), rsig->pin(idx));
791
8ee00ec Fix net division to cope with small output sizes.
steve authored
792
793 // Make an output signal that is the width of the l-value.
794 // Due to above calculation of rwidth, we know that the result
795 // will be no more then the l-value, so it is safe to connect
796 // all the result pins to the osig.
797
badad63 All NetObj objects have lex_string base names.
steve authored
798 NetNet*osig = new NetNet(scope, scope->local_symbol(),
694ff93 Add support for integer division.
steve authored
799 NetNet::IMPLICIT, lwidth);
800 osig->local_flag(true);
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
801 osig->set_signed(div->get_signed());
694ff93 Add support for integer division.
steve authored
802
8ee00ec Fix net division to cope with small output sizes.
steve authored
803 for (unsigned idx = 0 ; idx < rwidth ; idx += 1)
694ff93 Add support for integer division.
steve authored
804 connect(div->pin_Result(idx), osig->pin(idx));
805
8ee00ec Fix net division to cope with small output sizes.
steve authored
806
807 // If the lvalue is larger then the result, then pad the
808 // output with constant 0. This can happen for example in
809 // cases like this:
810 // wire [3;0] a, b;
811 // wire [7:0] r = a / b;
812
813 if (rwidth < osig->pin_count()) {
badad63 All NetObj objects have lex_string base names.
steve authored
814 NetConst*tmp = new NetConst(scope, scope->local_symbol(),
874bab1 NetObj constructor finally requires a scope.
steve authored
815 verinum::V0);
694ff93 Add support for integer division.
steve authored
816 des->add_node(tmp);
8ee00ec Fix net division to cope with small output sizes.
steve authored
817 for (unsigned idx = rwidth ; idx < osig->pin_count() ; idx += 1)
694ff93 Add support for integer division.
steve authored
818 connect(osig->pin(idx), tmp->pin(0));
819 }
820
821 return osig;
822 }
823
89d7176 Add support for modulus (Eric Aardoom)
steve authored
824 /*
825 * Elaborate a modulo gate.
826 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
827 NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
89d7176 Add support for modulus (Eric Aardoom)
steve authored
828 unsigned lwidth,
829 unsigned long rise,
830 unsigned long fall,
831 unsigned long decay) const
832 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
833 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
834 if (lsig == 0) return 0;
7793a49 Remove string paths from PExpr elaboration.
steve authored
835 NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
836 if (rsig == 0) return 0;
837
dd79885 Add structural modulus support down to vvp.
steve authored
838 unsigned rwidth = lwidth;
839 if (rwidth == 0) {
840 rwidth = lsig->pin_count();
841 if (rsig->pin_count() > rwidth)
842 rwidth = rsig->pin_count();
843 }
a275133 LPM objects store only their base names.
steve authored
844 NetModulo*mod = new NetModulo(scope, scope->local_symbol(), rwidth,
89d7176 Add support for modulus (Eric Aardoom)
steve authored
845 lsig->pin_count(),
846 rsig->pin_count());
847 des->add_node(mod);
848
849 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
850 connect(mod->pin_DataA(idx), lsig->pin(idx));
851 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
852 connect(mod->pin_DataB(idx), rsig->pin(idx));
853
854 if (lwidth == 0) lwidth = rwidth;
badad63 All NetObj objects have lex_string base names.
steve authored
855 NetNet*osig = new NetNet(scope, scope->local_symbol(),
89d7176 Add support for modulus (Eric Aardoom)
steve authored
856 NetNet::IMPLICIT, lwidth);
857 osig->local_flag(true);
858
859 unsigned cnt = osig->pin_count();
860 if (cnt > rwidth) cnt = rwidth;
861
862 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
863 connect(mod->pin_Result(idx), osig->pin(idx));
864
865 /* If the lvalue is larger then the result, then pad the
866 output with constant 0. */
867 if (cnt < osig->pin_count()) {
badad63 All NetObj objects have lex_string base names.
steve authored
868 NetConst*tmp = new NetConst(scope, scope->local_symbol(),
874bab1 NetObj constructor finally requires a scope.
steve authored
869 verinum::V0);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
870 des->add_node(tmp);
871 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
872 connect(osig->pin(idx), tmp->pin(0));
873 }
874
875 return osig;
876 }
877
7793a49 Remove string paths from PExpr elaboration.
steve authored
878 NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
ced7cc6 Structural logical or.
steve authored
879 unsigned lwidth,
880 unsigned long rise,
881 unsigned long fall,
882 unsigned long decay) const
883 {
ba309e6 Fix synthesis method for logical and/or
steve authored
884 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
885 NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
ced7cc6 Structural logical or.
steve authored
886 if (lsig == 0) {
887 cerr << get_line() << ": error: Cannot elaborate ";
888 left_->dump(cerr);
889 cerr << endl;
890 return 0;
891 }
892 if (rsig == 0) {
893 cerr << get_line() << ": error: Cannot elaborate ";
894 right_->dump(cerr);
895 cerr << endl;
896 return 0;
897 }
898
899 NetLogic*gate;
900 NetLogic*gate_t;
901 switch (op_) {
902 case 'a':
badad63 All NetObj objects have lex_string base names.
steve authored
903 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
904 3, NetLogic::AND, 1);
ced7cc6 Structural logical or.
steve authored
905 break;
906 case 'o':
badad63 All NetObj objects have lex_string base names.
steve authored
907 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
908 3, NetLogic::OR, 1);
ced7cc6 Structural logical or.
steve authored
909 break;
910 default:
911 assert(0);
912 }
913 gate->rise_time(rise);
914 gate->fall_time(fall);
915 gate->decay_time(decay);
916
917 // The first OR gate returns 1 if the left value is true...
918 if (lsig->pin_count() > 1) {
badad63 All NetObj objects have lex_string base names.
steve authored
919 gate_t = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
920 1+lsig->pin_count(), NetLogic::OR, 1);
ced7cc6 Structural logical or.
steve authored
921 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
922 connect(gate_t->pin(idx+1), lsig->pin(idx));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
923
ced7cc6 Structural logical or.
steve authored
924 connect(gate->pin(1), gate_t->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
925
926 /* The reduced logical value is a new nexus, create a
927 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
928 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
929 NetNet::IMPLICIT, 1);
930 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
931 connect(gate->pin(1), tmp->pin(0));
932
ced7cc6 Structural logical or.
steve authored
933 des->add_node(gate_t);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
934
ced7cc6 Structural logical or.
steve authored
935 } else {
936 connect(gate->pin(1), lsig->pin(0));
937 }
938
939 // The second OR gate returns 1 if the right value is true...
940 if (rsig->pin_count() > 1) {
badad63 All NetObj objects have lex_string base names.
steve authored
941 gate_t = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
942 1+rsig->pin_count(), NetLogic::OR, 1);
ced7cc6 Structural logical or.
steve authored
943 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
944 connect(gate_t->pin(idx+1), rsig->pin(idx));
945 connect(gate->pin(2), gate_t->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
946
947 /* The reduced logical value is a new nexus, create a
948 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
949 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
950 NetNet::IMPLICIT, 1);
951 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
952 connect(gate->pin(2), tmp->pin(0));
953
ced7cc6 Structural logical or.
steve authored
954 des->add_node(gate_t);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
955
ced7cc6 Structural logical or.
steve authored
956 } else {
957 connect(gate->pin(2), rsig->pin(0));
958 }
959
960 // The output is the AND/OR of the two logic values.
badad63 All NetObj objects have lex_string base names.
steve authored
961 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
ced7cc6 Structural logical or.
steve authored
962 osig->local_flag(true);
963 connect(gate->pin(0), osig->pin(0));
964 des->add_node(gate);
965 return osig;
966 }
967
7793a49 Remove string paths from PExpr elaboration.
steve authored
968 NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
aa8908c Multiplication all the way to simulation.
steve authored
969 unsigned lwidth,
970 unsigned long rise,
971 unsigned long fall,
972 unsigned long decay) const
973 {
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
974 verinum*lnum = left_->eval_const(des, scope);
975 verinum*rnum = right_->eval_const(des, scope);
976
977 /* Detect and handle the special case that both the operands
8f0c02c Spelling fixes.
steve authored
978 of the multiply are constant expressions. Evaluate the
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
979 value and make this a simple constant. */
980 if (lnum && rnum) {
981 verinum prod = *lnum * *rnum;
982 if (lwidth == 0)
983 lwidth = prod.len();
984
985 verinum res (verinum::V0, lwidth);
986 for (unsigned idx = 0
987 ; idx < prod.len() && idx < lwidth
988 ; idx += 1) {
989 res.set(idx, prod.get(idx));
990 }
991
badad63 All NetObj objects have lex_string base names.
steve authored
992 NetConst*odev = new NetConst(scope, scope->local_symbol(), res);
993 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
994 NetNet::IMPLICIT, lwidth);
995 for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
996 connect(odev->pin(idx), osig->pin(idx));
997
998 des->add_node(odev);
999 osig->local_flag(true);
1000 return osig;
1001 }
1002
7793a49 Remove string paths from PExpr elaboration.
steve authored
1003 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
aa8908c Multiplication all the way to simulation.
steve authored
1004 if (lsig == 0) return 0;
7793a49 Remove string paths from PExpr elaboration.
steve authored
1005 NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
aa8908c Multiplication all the way to simulation.
steve authored
1006 if (rsig == 0) return 0;
1007
4124273 Handle some special cases of unary 2's complement,
steve authored
1008 unsigned rwidth = lwidth;
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
1009 if (rwidth == 0) {
1010 rwidth = lsig->pin_count() + rsig->pin_count();
1011 }
1012
a275133 LPM objects store only their base names.
steve authored
1013 NetMult*mult = new NetMult(scope, scope->local_symbol(), rwidth,
aa8908c Multiplication all the way to simulation.
steve authored
1014 lsig->pin_count(),
1015 rsig->pin_count());
1016 des->add_node(mult);
1017
d18934d Sign extend NetMult inputs if result is signed.
steve authored
1018 mult->set_signed( lsig->get_signed() && rsig->get_signed() );
1019
aa8908c Multiplication all the way to simulation.
steve authored
1020 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
1021 connect(mult->pin_DataA(idx), lsig->pin(idx));
1022 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
1023 connect(mult->pin_DataB(idx), rsig->pin(idx));
1024
1025 if (lwidth == 0) lwidth = rwidth;
badad63 All NetObj objects have lex_string base names.
steve authored
1026 NetNet*osig = new NetNet(scope, scope->local_symbol(),
aa8908c Multiplication all the way to simulation.
steve authored
1027 NetNet::IMPLICIT, lwidth);
1028 osig->local_flag(true);
1029
1030 unsigned cnt = osig->pin_count();
1031 if (cnt > rwidth) cnt = rwidth;
1032
1033 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
1034 connect(mult->pin_Result(idx), osig->pin(idx));
1035
1036 /* If the lvalue is larger then the result, then pad the
1037 output with constant 0. */
1038 if (cnt < osig->pin_count()) {
badad63 All NetObj objects have lex_string base names.
steve authored
1039 NetConst*tmp = new NetConst(scope, scope->local_symbol(),
874bab1 NetObj constructor finally requires a scope.
steve authored
1040 verinum::V0);
aa8908c Multiplication all the way to simulation.
steve authored
1041 des->add_node(tmp);
1042 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
1043 connect(osig->pin(idx), tmp->pin(0));
1044 }
1045
1046 return osig;
1047 }
1048
7793a49 Remove string paths from PExpr elaboration.
steve authored
1049 NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1050 unsigned lwidth,
1051 unsigned long rise,
1052 unsigned long fall,
1053 unsigned long decay) const
1054 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
1055 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1056 if (lsig == 0) return 0;
1057
9e5ff89 Add structural reduction NAND,
steve authored
1058 if (lsig->pin_count() > lwidth)
1059 lwidth = lsig->pin_count();
1060
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1061 bool right_flag = op_ == 'r' || op_ == 'R';
1062 bool signed_flag = op_ == 'R';
1063
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1064 /* Handle the special case of a constant shift amount. There
1065 is no reason in this case to create a gate at all, just
1066 connect the lsig to the osig with the bit positions
1067 shifted. */
bf72f39 eval_const uses scope instead of a string path.
steve authored
1068 if (verinum*rval = right_->eval_const(des, scope)) {
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1069 assert(rval->is_defined());
1070 unsigned dist = rval->as_ulong();
4124273 Handle some special cases of unary 2's complement,
steve authored
1071 if (dist > lwidth)
1072 dist = lwidth;
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1073
1074 /* Very special case, constant 0 shift. */
1075 if (dist == 0) return lsig;
1076
badad63 All NetObj objects have lex_string base names.
steve authored
1077 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4124273 Handle some special cases of unary 2's complement,
steve authored
1078 NetNet::WIRE, lwidth);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1079 osig->local_flag(true);
1080
badad63 All NetObj objects have lex_string base names.
steve authored
1081 NetConst*zero = new NetConst(scope, scope->local_symbol(),
874bab1 NetObj constructor finally requires a scope.
steve authored
1082 verinum::V0);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1083 des->add_node(zero);
1084
1085 if (op_ == 'l') {
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1086 /* Left shift means put some zeros on the bottom
1087 of the vector. */
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1088 unsigned idx;
1089 for (idx = 0 ; idx < dist ; idx += 1)
1090 connect(osig->pin(idx), zero->pin(0));
4124273 Handle some special cases of unary 2's complement,
steve authored
1091 for ( ; (idx<lwidth) && ((idx-dist) < lsig->pin_count())
1092 ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1093 connect(osig->pin(idx), lsig->pin(idx-dist));
4124273 Handle some special cases of unary 2's complement,
steve authored
1094 for ( ; idx < lwidth ; idx += 1)
1095 connect(osig->pin(idx), zero->pin(0));
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1096
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1097 } else if (op_ == 'R') {
1098 /* Signed right shift. */
1099 unsigned idx;
1100 unsigned keep = lsig->pin_count()-dist;
1101 for (idx = 0 ; idx < keep ; idx += 1)
1102 connect(osig->pin(idx), lsig->pin(idx+dist));
1103 for (idx = keep ; idx < lwidth ; idx += 1)
1104 connect(osig->pin(idx), lsig->pin(keep+dist-1));
1105
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1106 } else {
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1107 /* Unsigned right shift. */
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1108 assert(op_ == 'r');
1109 unsigned idx;
1110 unsigned keep = lsig->pin_count()-dist;
1111 for (idx = 0 ; idx < keep ; idx += 1)
1112 connect(osig->pin(idx), lsig->pin(idx+dist));
4124273 Handle some special cases of unary 2's complement,
steve authored
1113 for (idx = keep ; idx < lwidth ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1114 connect(osig->pin(idx), zero->pin(0));
1115 }
1116
1117 return osig;
1118 }
1119
9e5ff89 Add structural reduction NAND,
steve authored
1120 // Calculate the number of useful bits for the shift amount,
1121 // and elaborate the right_ expression as the shift amount.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1122 unsigned dwid = 0;
61195c5 Harmless fixup of warnings.
steve authored
1123 while ((1U << dwid) < lwidth)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1124 dwid += 1;
1125
7793a49 Remove string paths from PExpr elaboration.
steve authored
1126 NetNet*rsig = right_->elaborate_net(des, scope, dwid, 0, 0, 0);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1127 if (rsig == 0) return 0;
1128
9e5ff89 Add structural reduction NAND,
steve authored
1129 // Make the shift device itself, and the output
1130 // NetNet. Connect the Result output pins to the osig signal
a275133 LPM objects store only their base names.
steve authored
1131 NetCLShift*gate = new NetCLShift(scope, scope->local_symbol(),
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1132 lwidth, rsig->pin_count(),
1133 right_flag, signed_flag);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1134
badad63 All NetObj objects have lex_string base names.
steve authored
1135 NetNet*osig = new NetNet(scope, scope->local_symbol(),
9e5ff89 Add structural reduction NAND,
steve authored
1136 NetNet::WIRE, lwidth);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1137 osig->local_flag(true);
1138
9e5ff89 Add structural reduction NAND,
steve authored
1139 for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1140 connect(osig->pin(idx), gate->pin_Result(idx));
9e5ff89 Add structural reduction NAND,
steve authored
1141
1142 // Connect the lsig (the left expression) to the Data input,
1143 // and pad it if necessary with constant zeros.
1144 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1145 connect(lsig->pin(idx), gate->pin_Data(idx));
9e5ff89 Add structural reduction NAND,
steve authored
1146
1147 if (lsig->pin_count() < lwidth) {
badad63 All NetObj objects have lex_string base names.
steve authored
1148 NetConst*zero = new NetConst(scope, scope->local_symbol(),
874bab1 NetObj constructor finally requires a scope.
steve authored
1149 verinum::V0);
badad63 All NetObj objects have lex_string base names.
steve authored
1150 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
1151 NetNet::IMPLICIT, 1);
1152 tmp->local_flag(true);
9e5ff89 Add structural reduction NAND,
steve authored
1153 des->add_node(zero);
ba7fdb5 Add a signal to nexus of padding constant.
steve authored
1154 connect(zero->pin(0), tmp->pin(0));
9e5ff89 Add structural reduction NAND,
steve authored
1155 for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
1156 connect(zero->pin(0), gate->pin_Data(idx));
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1157 }
1158
9e5ff89 Add structural reduction NAND,
steve authored
1159 // Connect the rsig (the shift amount expression) to the
1160 // Distance input.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1161 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
1162 connect(rsig->pin(idx), gate->pin_Distance(idx));
1163
1164 des->add_node(gate);
1165
1166 return osig;
1167 }
1168
cdb99e7 Elaborate net repeat concatenations.
steve authored
1169 /*
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1170 * This method elaborates a call to a function in the context of a
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1171 * continuous assignment. The definition of the function contains a
1172 * list of the ports, and an output port. The NetEUFunc that I create
1173 * here has a port for all the input ports and the output port. The
1174 * ports are connected by pins.
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1175 */
5d1d99a Handle signed magnitude compare all the
steve authored
1176 NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
1177 unsigned width,
1178 unsigned long rise,
1179 unsigned long fall,
1180 unsigned long decay,
1181 Link::strength_t drive0,
1182 Link::strength_t drive1) const
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1183 {
1184 unsigned errors = 0;
1185 unsigned func_pins = 0;
1186
5d1d99a Handle signed magnitude compare all the
steve authored
1187 /* Handle the special case that the function call is to
1188 $signed. This takes a single expression argument, and
1189 forces it to be a signed result. Otherwise, it is as if the
1190 $signed did not exist. */
1191 if (strcmp(path_.peek_name(0), "$signed") == 0) {
1192 if ((parms_.count() != 1) || (parms_[0] == 0)) {
1193 cerr << get_line() << ": error: The $signed() function "
1194 << "takes exactly one(1) argument." << endl;
1195 des->errors += 1;
1196 return 0;
1197 }
1198
1199 PExpr*expr = parms_[0];
1200 NetNet*sub = expr->elaborate_net(des, scope, width, rise,
1201 fall, decay, drive0, drive1);
1202 sub->set_signed(true);
1203 return sub;
1204 }
7f67afe Add support for $unsigned.
steve authored
1205 /* handle $unsigned like $signed */
1206 if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
1207 if ((parms_.count() != 1) || (parms_[0] == 0)) {
1208 cerr << get_line() << ": error: The $unsigned() function "
1209 << "takes exactly one(1) argument." << endl;
1210 des->errors += 1;
1211 return 0;
1212 }
1213
1214 PExpr*expr = parms_[0];
1215 NetNet*sub = expr->elaborate_net(des, scope, width, rise,
1216 fall, decay, drive0, drive1);
1217 sub->set_signed(false);
1218 return sub;
1219 }
5d1d99a Handle signed magnitude compare all the
steve authored
1220
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1221 /* Look up the function definition. */
1222 NetFuncDef*def = des->find_function(scope, path_);
1223 if (def == 0) {
1224 cerr << get_line() << ": error: No function " << path_ <<
1225 " in this context (" << scope->name() << ")." << endl;
1226 des->errors += 1;
1227 return 0;
1228 }
1229 assert(def);
1230
1231 NetScope*dscope = def->scope();
1232 assert(dscope);
1233
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1234 /* This must be a ufuction that returns a signal. */
1235 assert(def->return_sig());
1236
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1237 /* check the validity of the parameters. */
1238 if (! check_call_matches_definition_(des, dscope))
1239 return 0;
1240
1241 /* Elaborate all the parameters of the function call,
1242 and collect the resulting NetNet objects. All the
1243 parameters take on the size of the target port. */
1244
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1245 svector<NetNet*> eparms (def->port_count());
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1246 for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1247 const NetNet* port_reg = def->port(idx);
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1248 NetNet*tmp = parms_[idx]->elaborate_net(des, scope,
1249 port_reg->pin_count(),
1250 0, 0, 0,
1251 Link::STRONG,
1252 Link::STRONG);
1253 if (tmp == 0) {
1254 cerr << get_line() << ": error: Unable to elaborate "
1255 << "port " << idx << " of call to " << path_ <<
1256 "." << endl;
1257 errors += 1;
1258 continue;
1259 }
1260
1261 func_pins += tmp->pin_count();
1262 eparms[idx] = tmp;
1263 }
1264
1265 if (errors > 0)
1266 return 0;
1267
1268
1269 NetUserFunc*net = new NetUserFunc(scope,
27af95d Use perm_strings for named langiage items.
steve authored
1270 scope->local_symbol(),
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1271 dscope);
1272 des->add_node(net);
1273
1274 /* Create an output signal and connect it to the output pins
1275 of the function net. */
badad63 All NetObj objects have lex_string base names.
steve authored
1276 NetNet*osig = new NetNet(scope, scope->local_symbol(),
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1277 NetNet::WIRE,
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1278 def->return_sig()->pin_count());
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1279 osig->local_flag(true);
1280
1281 for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
1282 connect(net->port_pin(0, idx), osig->pin(idx));
1283
1284 /* Connect the parameter pins to the parameter expressions. */
1285 for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1286 const NetNet* port = def->port(idx);
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1287 NetNet*cur = eparms[idx];
1288
1289 NetNet*tmp = pad_to_width(des, cur, port->pin_count());
1290
1291 for (unsigned pin = 0 ; pin < port->pin_count() ; pin += 1)
1292 connect(net->port_pin(idx+1, pin), tmp->pin(pin));
1293 }
1294
1295 return osig;
1296 }
1297
1298
1299 /*
cdb99e7 Elaborate net repeat concatenations.
steve authored
1300 * The concatenation operator, as a net, is a wide signal that is
1301 * connected to all the pins of the elaborated expression nets.
1302 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
1303 NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
cdb99e7 Elaborate net repeat concatenations.
steve authored
1304 unsigned,
1305 unsigned long rise,
1306 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1307 unsigned long decay,
1308 Link::strength_t drive0,
1309 Link::strength_t drive1) const
cdb99e7 Elaborate net repeat concatenations.
steve authored
1310 {
1311 svector<NetNet*>nets (parms_.count());
1312 unsigned pins = 0;
1313 unsigned errors = 0;
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1314 unsigned repeat = 1;
cdb99e7 Elaborate net repeat concatenations.
steve authored
1315
1316 if (repeat_) {
bf72f39 eval_const uses scope instead of a string path.
steve authored
1317 verinum*rep = repeat_->eval_const(des, scope);
cdb99e7 Elaborate net repeat concatenations.
steve authored
1318 if (rep == 0) {
1319 cerr << get_line() << ": internal error: Unable to "
1320 << "evaluate constant repeat expression." << endl;
1321 des->errors += 1;
1322 return 0;
1323 }
1324
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1325 repeat = rep->as_ulong();
cdb99e7 Elaborate net repeat concatenations.
steve authored
1326
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1327 if (repeat == 0) {
1328 cerr << get_line() << ": error: Invalid repeat value."
1329 << endl;
1330 des->errors += 1;
1331 delete rep;
1332 return 0;
cdb99e7 Elaborate net repeat concatenations.
steve authored
1333 }
1334 }
1335
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
1336 /* The operands of the concatenation must contain all
1337 self-determined arguments. Set this flag to force an error
1338 message if this is not the case. */
1339 const bool save_flag = must_be_self_determined_flag;
1340 must_be_self_determined_flag = true;
1341
cdb99e7 Elaborate net repeat concatenations.
steve authored
1342 /* Elaborate the operands of the concatenation. */
1343 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
1344
f526d23 Check for missing concat subexpressions (PR#11)
steve authored
1345 if (parms_[idx] == 0) {
1346 cerr << get_line() << ": error: Empty expressions "
1347 << "not allowed in concatenations." << endl;
1348 errors += 1;
1349 continue;
1350 }
1351
79b1c51 Detect indefinite widths where definite widths are required.
steve authored
1352 /* Look for the special case of an unsized number in a
1353 concatenation expression. Mark this as an error, but
1354 allow elaboration to continue to see if I can find
1355 more errors. */
1356
1357 if (PENumber*tmp = dynamic_cast<PENumber*>(parms_[idx])) {
1358 if (tmp->value().has_len() == false) {
1359 cerr << get_line() << ": error: Number "
1360 << tmp->value() << " with indefinite size"
1361 << " in concatenation." << endl;
1362 errors += 1;
1363 }
1364 }
1365
7793a49 Remove string paths from PExpr elaboration.
steve authored
1366 nets[idx] = parms_[idx]->elaborate_net(des, scope, 0,
cdb99e7 Elaborate net repeat concatenations.
steve authored
1367 rise,fall,decay);
1368 if (nets[idx] == 0)
1369 errors += 1;
1370 else
1371 pins += nets[idx]->pin_count();
1372 }
1373
d1f0bcf Catch unsized expressions in continuous assigns.
steve authored
1374 must_be_self_determined_flag = save_flag;
1375
cdb99e7 Elaborate net repeat concatenations.
steve authored
1376 /* If any of the sub expressions failed to elaborate, then
1377 delete all those that did and abort myself. */
1378 if (errors) {
1379 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
1380 if (nets[idx]) delete nets[idx];
1381 }
1382 des->errors += 1;
1383 return 0;
1384 }
1385
1386 /* Make the temporary signal that connects to all the
1387 operands, and connect it up. Scan the operands of the
1388 concat operator from least significant to most significant,
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1389 which is opposite from how they are given in the list.
1390
1391 Allow for a repeat count other then 1 by repeating the
1392 connect loop as many times as necessary. */
1393
badad63 All NetObj objects have lex_string base names.
steve authored
1394 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1395 NetNet::IMPLICIT, pins * repeat);
1396
cdb99e7 Elaborate net repeat concatenations.
steve authored
1397 pins = 0;
4819d54 Fix repeat concatenation with multiple expressions (PR#10)
steve authored
1398 for (unsigned rpt = 0 ; rpt < repeat ; rpt += 1)
1399 for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
1400 NetNet*cur = nets[idx-1];
1401 for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
1402 connect(osig->pin(pins), cur->pin(pin));
1403 pins += 1;
1404 }
cdb99e7 Elaborate net repeat concatenations.
steve authored
1405 }
1406
1407 osig->local_flag(true);
1408 return osig;
1409 }
1410
9ef4937 Add support for non-constant bit select.
steve authored
1411 /*
7b6678b Fix reverse bit ordered bit select in continuous assignment.
steve authored
1412 * This private method handles the special case that we have a
9ef4937 Add support for non-constant bit select.
steve authored
1413 * non-constant bit-select of an identifier. We already know that the
1414 * signal that is represented is "sig".
1415 */
1416 NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
1417 NetNet*sig,
1418 unsigned long rise,
1419 unsigned long fall,
1420 unsigned long decay,
1421 Link::strength_t drive0,
1422 Link::strength_t drive1) const
1423 {
1424 /* Elaborate the selector. */
1425 NetNet*sel = msb_->elaborate_net(des, scope, 0, 0, 0, 0);
1426
7b6678b Fix reverse bit ordered bit select in continuous assignment.
steve authored
1427 unsigned sig_width = sig->pin_count();
ca0a9fa Only build a mux as wide as can be selected.
steve authored
1428
1429 /* Detect the case of some bits not accessible by the given
1430 select. Figure out how many bits can be selected by the
1431 full range of the select, and limit the input of the mux to
1432 that width. */
1433 { unsigned max_width_by_sel = 1 << sel->pin_count();
1434 if (sig_width > max_width_by_sel)
1435 sig_width = max_width_by_sel;
1436 }
1437
a275133 LPM objects store only their base names.
steve authored
1438 NetMux*mux = new NetMux(scope, scope->local_symbol(), 1,
7b6678b Fix reverse bit ordered bit select in continuous assignment.
steve authored
1439 sig_width, sel->pin_count());
9ef4937 Add support for non-constant bit select.
steve authored
1440
7b6678b Fix reverse bit ordered bit select in continuous assignment.
steve authored
1441 /* Connect the signal bits to the mux. Account for the
1442 direction of the numbering (lsb to msb vs. msb to lsb) by
1443 swapping the connection order. */
1444
1445 if (sig->msb() > sig->lsb()) {
1446
1447 sel = add_to_net(des, sel, -sig->lsb());
1448 for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
1449 connect(mux->pin_Data(0, idx), sig->pin(idx));
1450 } else {
1451
1452 sel = add_to_net(des, sel, -sig->msb());
1453 for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
1454 connect(mux->pin_Data(0, idx), sig->pin(sig_width-idx-1));
1455 }
9ef4937 Add support for non-constant bit select.
steve authored
1456
1457 for (unsigned idx = 0 ; idx < sel->pin_count() ; idx += 1)
1458 connect(mux->pin_Sel(idx), sel->pin(idx));
1459
badad63 All NetObj objects have lex_string base names.
steve authored
1460 NetNet*out = new NetNet(scope, scope->local_symbol(),
9ef4937 Add support for non-constant bit select.
steve authored
1461 NetNet::IMPLICIT, 1);
1462 connect(mux->pin_Result(0), out->pin(0));
1463
1464 des->add_node(mux);
1465 out->local_flag(true);
1466 return out;
1467 }
1468
7793a49 Remove string paths from PExpr elaboration.
steve authored
1469 NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
a81dcd7 Support memories in continuous assignments.
steve authored
1470 unsigned lwidth,
1471 unsigned long rise,
1472 unsigned long fall,
b90cda1 Carry strength values from Verilog source to the
steve authored
1473 unsigned long decay,
1474 Link::strength_t drive0,
1475 Link::strength_t drive1) const
a81dcd7 Support memories in continuous assignments.
steve authored
1476 {
6937945 Remove find_memory method from Design class.
steve authored
1477 assert(scope);
a81dcd7 Support memories in continuous assignments.
steve authored
1478
6937945 Remove find_memory method from Design class.
steve authored
1479 NetNet* sig = 0;
1480 NetMemory* mem = 0;
1481 NetVariable* var = 0;
1482 const NetExpr*par = 0;
1483 NetEvent* eve = 0;
1222153 Keep parameter constants for the ivl_target API.
steve authored
1484
6937945 Remove find_memory method from Design class.
steve authored
1485 symbol_search(des, scope, path_, sig, mem, var, par, eve);
a81dcd7 Support memories in continuous assignments.
steve authored
1486
6937945 Remove find_memory method from Design class.
steve authored
1487 /* If the identifier is a memory instead of a signal,
1488 then handle it elsewhere. Create a RAM. */
1489 if (mem != 0) {
1490 return elaborate_net_ram_(des, scope, mem, lwidth,
1491 rise, fall, decay);
1492 }
a81dcd7 Support memories in continuous assignments.
steve authored
1493
6937945 Remove find_memory method from Design class.
steve authored
1494 /* If this is a parameter name, then create a constant node
1495 that connects to a signal with the correct name. */
1496 if (par != 0) {
a81dcd7 Support memories in continuous assignments.
steve authored
1497
6937945 Remove find_memory method from Design class.
steve authored
1498 const NetEConst*pc = dynamic_cast<const NetEConst*>(par);
1499 assert(pc);
1500 verinum pvalue = pc->value();
5d1d99a Handle signed magnitude compare all the
steve authored
1501
27af95d Use perm_strings for named langiage items.
steve authored
1502 sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
6937945 Remove find_memory method from Design class.
steve authored
1503 NetNet::IMPLICIT, pc->expr_width());
1504 NetConst*cp = new NetConst(scope, scope->local_symbol(),
1505 pvalue);
1506 des->add_node(cp);
1507 for (unsigned idx = 0; idx < sig->pin_count(); idx += 1)
1508 connect(sig->pin(idx), cp->pin(idx));
1509 }
a81dcd7 Support memories in continuous assignments.
steve authored
1510
930e513 Catch real variables in net expressions.
steve authored
1511 if (var != 0) {
1512 cerr << get_line() << ": sorry: " << path_
1513 << " is a real in a net/wire context." << endl;
1514 des->errors += 1;
1515 return 0;
1516 }
1517
180bfc5 Detect and prevent implicit declaration of hierarchical names.
steve authored
1518 /* Check for the error case that the name is not found, and it
1519 is hierarchical. We can't just create a name in another
1520 scope, it's just not allowed. */
1521 if (sig == 0 && path_.component_count() != 1) {
1522 cerr << get_line() << ": error: The hierarchical name "
1523 << path_ << " is undefined in "
1524 << scope->name() << "." << endl;
1525
1526 hname_t tmp_path = path_;
1527 delete[] tmp_path.remove_tail_name();
1528
1529 NetScope*tmp_scope = des->find_scope(scope, tmp_path);
1530 if (tmp_scope == 0) {
1531 cerr << get_line() << ": : I can't even find "
1532 << "the scope " << tmp_path << "." << endl;
1533 }
1534
1535 des->errors += 1;
1536 return 0;
1537 }
1538
6937945 Remove find_memory method from Design class.
steve authored
1539 /* Fallback, this may be an implicitly declared net. */
1540 if (sig == 0) {
9949040 Add support for the default_nettype directive.
steve authored
1541 NetNet::Type nettype = scope->default_nettype();
27af95d Use perm_strings for named langiage items.
steve authored
1542 sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
9949040 Add support for the default_nettype directive.
steve authored
1543 nettype, 1);
48de739 Switch to control warnings.
steve authored
1544
9949040 Add support for the default_nettype directive.
steve authored
1545 if (error_implicit || (nettype == NetNet::NONE)) {
6937945 Remove find_memory method from Design class.
steve authored
1546 cerr << get_line() << ": error: "
1547 << scope->name() << "." << path_.peek_name(0)
1548 << " not defined in this scope." << endl;
1549 des->errors += 1;
0976fd3 Do not allow implicit wires in sensitivity lists.
steve authored
1550
6937945 Remove find_memory method from Design class.
steve authored
1551 } else if (warn_implicit) {
1552 cerr << get_line() << ": warning: implicit "
1553 "definition of wire " << scope->name()
1554 << "." << path_.peek_name(0) << "." << endl;
a81dcd7 Support memories in continuous assignments.
steve authored
1555 }
1556 }
1557
1558 assert(sig);
1559
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1560 /* Catch the case of a non-constant bit select. That should be
1561 handled elsewhere. */
1562 if (msb_ && !lsb_) {
bf72f39 eval_const uses scope instead of a string path.
steve authored
1563 verinum*mval = msb_->eval_const(des, scope);
a81dcd7 Support memories in continuous assignments.
steve authored
1564 if (mval == 0) {
9ef4937 Add support for non-constant bit select.
steve authored
1565 return elaborate_net_bitmux_(des, scope, sig, rise,
1566 fall, decay, drive0, drive1);
a81dcd7 Support memories in continuous assignments.
steve authored
1567 }
9ef4937 Add support for non-constant bit select.
steve authored
1568
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1569 delete mval;
1570 }
1571
1572 unsigned midx, lidx;
1573 if (! eval_part_select_(des, scope, sig, midx, lidx))
1574 return 0;
2a08824 Detect muxing Vz as a bufufN.
steve authored
1575
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1576 unsigned part_count = midx-lidx+1;
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
1577
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1578 if (part_count != sig->vector_width()) {
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
1579 if (debug_elaborate) {
1580 cerr << get_line() << ": debug: Elaborate part select "
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1581 << sig->name() << "[base="<<lidx
1582 << " wid=" << part_count << "]" << endl;
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
1583 }
1584
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1585 NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
1586 NetPartSelect::VP);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
1587 ps->set_line(*sig);
1588 des->add_node(ps);
1589
1590 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1591 NetNet::WIRE, part_count-1, 0);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
1592 tmp->local_flag(true);
1593 connect(tmp->pin(0), ps->pin(0));
1594
a81dcd7 Support memories in continuous assignments.
steve authored
1595 sig = tmp;
1596 }
1597
9e94afe Use PartSelect/PV and VP to handle part selects through ports.
steve authored
1598
a81dcd7 Support memories in continuous assignments.
steve authored
1599 return sig;
1600 }
1601
1602 /*
8f0c02c Spelling fixes.
steve authored
1603 * When I run into an identifier in an expression that refers to a
a81dcd7 Support memories in continuous assignments.
steve authored
1604 * memory, create a RAM port object.
1605 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
1606 NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
a81dcd7 Support memories in continuous assignments.
steve authored
1607 NetMemory*mem, unsigned lwidth,
1608 unsigned long rise,
1609 unsigned long fall,
1610 unsigned long decay) const
1611 {
8d8f1e2 Move signal tables to the NetScope class.
steve authored
1612 assert(scope);
1613
a81dcd7 Support memories in continuous assignments.
steve authored
1614 if (msb_ == 0) {
1615 cerr << get_line() << ": error: memory reference without"
1616 " the required index expression." << endl;
1617 des->errors += 1;
1618 return 0;
1619 }
1620
8dab4c6 memory index need not be self determined width.
steve authored
1621