Skip to content

HTTPS clone URL

Subversion checkout URL

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