Skip to content

HTTPS clone URL

Subversion checkout URL

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