Skip to content

HTTPS clone URL

Subversion checkout URL

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