Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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