Skip to content

HTTPS clone URL

Subversion checkout URL

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