Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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