Skip to content
This repository
Newer
Older
100644 1914 lines (1623 sloc) 57.628 kb
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
1 /*
b734ecf0 »
2000-02-23 Macintosh compilers do not support ident.
2 * Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
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 */
b734ecf0 »
2000-02-23 Macintosh compilers do not support ident.
19 #if !defined(WINNT) && !defined(macintosh)
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
20 #ident "$Id: elab_net.cc,v 1.82 2001/12/03 04:47:14 steve Exp $"
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
21 #endif
22
b825f8d2 »
2001-07-25 Create a config.h.in file to hold all the config
23 # include "config.h"
24
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
25 # include "PExpr.h"
26 # include "netlist.h"
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
27 # include "netmisc.h"
48de7395 »
2000-03-17 Switch to control warnings.
28 # include "compiler.h"
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
29
b825f8d2 »
2001-07-25 Create a config.h.in file to hold all the config
30 # include <iostream>
31
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
32 /*
33 * Elaborating binary operations generally involves elaborating the
34 * left and right expressions, then making an output wire and
35 * connecting the lot together with the right kind of gate.
36 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
37 NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
38 unsigned width,
39 unsigned long rise,
40 unsigned long fall,
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
41 unsigned long decay,
42 Link::strength_t drive0,
43 Link::strength_t drive1) const
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
44 {
45 switch (op_) {
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
46 case '*':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
47 return elaborate_net_mul_(des, scope, width, rise, fall, decay);
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
48 case '%':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
49 return elaborate_net_mod_(des, scope, width, rise, fall, decay);
694ff934 »
2000-04-01 Add support for integer division.
50 case '/':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
51 return elaborate_net_div_(des, scope, width, rise, fall, decay);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
52 case '+':
53 case '-':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
54 return elaborate_net_add_(des, scope, width, rise, fall, decay);
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
55 case '|': // Bitwise OR
56 case '&':
57 case '^':
58 case 'X': // Exclusing NOR
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
59 return elaborate_net_bit_(des, scope, width, rise, fall, decay);
b8c5aff0 »
2001-07-07 Generate !== an an inverted ===
60 case 'E': // === (case equals)
61 case 'e': // ==
62 case 'N': // !== (case not-equals)
63 case 'n': // !=
513ade9b »
1999-11-14 Support combinatorial comparators.
64 case '<':
65 case '>':
66 case 'L': // <=
67 case 'G': // >=
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
68 return elaborate_net_cmp_(des, scope, width, rise, fall, decay);
ced7cc6d »
1999-12-16 Structural logical or.
69 case 'a': // && (logical and)
70 case 'o': // || (logical or)
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
71 return elaborate_net_log_(des, scope, width, rise, fall, decay);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
72 case 'l': // <<
73 case 'r': // >>
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
74 return elaborate_net_shift_(des, scope, width, rise, fall, decay);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
75 }
76
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
77 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
78 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
79 if (lsig == 0) {
80 cerr << get_line() << ": error: Cannot elaborate ";
81 left_->dump(cerr);
82 cerr << endl;
83 return 0;
84 }
85 if (rsig == 0) {
86 cerr << get_line() << ": error: Cannot elaborate ";
87 right_->dump(cerr);
88 cerr << endl;
89 return 0;
90 }
91
92 NetNet*osig;
93 NetNode*gate;
94 NetNode*gate_t;
95
96 switch (op_) {
97 case '^': // XOR
57d28e4f »
2000-01-18 Support structural XNOR.
98 case 'X': // XNOR
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
99 case '&': // AND
100 case '|': // Bitwise OR
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
101 assert(0);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
102 break;
103
104 case 'E': // === (Case equals)
105 case 'e': // ==
106 case 'n': // !=
513ade9b »
1999-11-14 Support combinatorial comparators.
107 case '<':
108 case '>':
109 case 'G': // >=
110 case 'L': // <=
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
111 assert(0);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
112 break;
113
114 case '+':
115 assert(0);
116 break;
117
118 case 'l':
119 case 'r':
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
120 assert(0);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
121 break;
122 default:
123 cerr << get_line() << ": internal error: unsupported"
124 " combinational operator (" << op_ << ")." << endl;
125 des->errors += 1;
126 osig = 0;
127 }
128
129 if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
130 delete tmp;
131 if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
132 delete tmp;
133
134 return osig;
135 }
136
137 /*
138 * Elaborate the structural +/- as an AddSub object. Connect DataA and
139 * DataB to the parameters, and connect the output signal to the
140 * Result. In this context, the device is a combinational adder with
141 * fixed direction, so leave Add_Sub unconnected and set the
142 * LPM_Direction property.
143 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
144 NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
145 unsigned lwidth,
146 unsigned long rise,
147 unsigned long fall,
148 unsigned long decay) const
149 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
150 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
151 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
152 if (lsig == 0) {
153 cerr << get_line() << ": error: Cannot elaborate ";
154 left_->dump(cerr);
155 cerr << endl;
156 return 0;
157 }
158 if (rsig == 0) {
159 cerr << get_line() << ": error: Cannot elaborate ";
160 right_->dump(cerr);
161 cerr << endl;
162 return 0;
163 }
164
165 NetNet*osig;
166 NetNode*gate;
167 NetNode*gate_t;
168
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
169 string name = scope->local_hsymbol();
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
170 unsigned width = lsig->pin_count();
171 if (rsig->pin_count() > lsig->pin_count())
172 width = rsig->pin_count();
173
d78c7392 »
2001-02-08 Remove dead code.
174
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
175 /* The owidth is the output width of the lpm_add_sub
176 device. If the desired with is greater then the width of
177 the operands, then widen the adder and let code below pad
178 the operands. If this is an adder, we can take advantage of
179 the carry bit. */
180 unsigned owidth = width;
181 switch (op_) {
182 case '+':
183 if (lwidth > owidth) {
184 owidth = lwidth;
185 width = lwidth-1;
186 }
187 break;
188 case '-':
189 if (lwidth > owidth) {
190 owidth = lwidth;
191 width = lwidth;
192 }
193 break;
194 default:
195 assert(0);
196 }
d78c7392 »
2001-02-08 Remove dead code.
197
d54cc14c »
1999-12-16 Simulate carry output on adders.
198
acfb5c17 »
2000-04-28 Over agressive signal elimination in constant probadation.
199 // Pad out the operands, if necessary, the match the width of
200 // the adder device.
201 if (lsig->pin_count() < width)
2b0aaec8 »
2001-02-15 FreeBSD port has a maintainer now.
202 lsig = pad_to_width(des, lsig, width);
acfb5c17 »
2000-04-28 Over agressive signal elimination in constant probadation.
203
204 if (rsig->pin_count() < width)
2b0aaec8 »
2001-02-15 FreeBSD port has a maintainer now.
205 rsig = pad_to_width(des, rsig, width);
acfb5c17 »
2000-04-28 Over agressive signal elimination in constant probadation.
206
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
207 // Make the adder as wide as the widest operand
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
208 osig = new NetNet(scope, scope->local_hsymbol(),
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
209 NetNet::WIRE, owidth);
210 osig->local_flag(true);
f4809436 »
2001-06-07 Support structural addition.
211 NetAddSub*adder = new NetAddSub(scope, name, width);
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
212
213 // Connect the adder to the various parts.
214 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
215 connect(lsig->pin(idx), adder->pin_DataA(idx));
216 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
217 connect(rsig->pin(idx), adder->pin_DataB(idx));
d54cc14c »
1999-12-16 Simulate carry output on adders.
218 for (unsigned idx = 0 ; idx < width ; idx += 1)
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
219 connect(osig->pin(idx), adder->pin_Result(idx));
d54cc14c »
1999-12-16 Simulate carry output on adders.
220 if (owidth > width)
221 connect(osig->pin(width), adder->pin_Cout());
e1bbbe56 »
1999-10-31 Include subtraction in LPM_ADD_SUB device.
222
223 gate = adder;
224 gate->rise_time(rise);
225 gate->fall_time(fall);
226 gate->decay_time(decay);
227 des->add_node(gate);
228
229 switch (op_) {
230 case '+':
231 gate->attribute("LPM_Direction", "ADD");
232 break;
233 case '-':
234 gate->attribute("LPM_Direction", "SUB");
235 break;
236 }
237
238
239 return osig;
240 }
241
242 /*
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
243 * Elaborate various bitwise logic operators. These are all similar in
244 * that they take operants of equal width, and each bit does not
245 * affect any other bits. Also common about all this is how bit widths
246 * of the operands are handled, when they do not match.
247 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
248 NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
249 unsigned width,
250 unsigned long rise,
251 unsigned long fall,
252 unsigned long decay) const
253 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
254 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
255 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
256 if (lsig == 0) {
257 cerr << get_line() << ": error: Cannot elaborate ";
258 left_->dump(cerr);
259 cerr << endl;
260 return 0;
261 }
262 if (rsig == 0) {
263 cerr << get_line() << ": error: Cannot elaborate ";
264 right_->dump(cerr);
265 cerr << endl;
266 return 0;
267 }
268
269 if (lsig->pin_count() < rsig->pin_count())
2b0aaec8 »
2001-02-15 FreeBSD port has a maintainer now.
270 lsig = pad_to_width(des, lsig, rsig->pin_count());
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
271 if (rsig->pin_count() < lsig->pin_count())
2b0aaec8 »
2001-02-15 FreeBSD port has a maintainer now.
272 rsig = pad_to_width(des, rsig, lsig->pin_count());
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
273
274 if (lsig->pin_count() != rsig->pin_count()) {
275 cerr << get_line() << ": internal error: lsig pin count ("
276 << lsig->pin_count() << ") != rsig pin count ("
277 << rsig->pin_count() << ")." << endl;
278 des->errors += 1;
279 return 0;
280 }
281
282 assert(lsig->pin_count() == rsig->pin_count());
283
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
284 NetNet*osig = new NetNet(scope, scope->local_hsymbol(), NetNet::WIRE,
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
285 lsig->pin_count());
286 osig->local_flag(true);
287
288 switch (op_) {
289 case '^': // XOR
290 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
291 NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
76e2c509 »
2000-10-07 Put logic devices into scopes.
292 3, NetLogic::XOR);
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
293 connect(gate->pin(1), lsig->pin(idx));
294 connect(gate->pin(2), rsig->pin(idx));
295 connect(gate->pin(0), osig->pin(idx));
296 gate->rise_time(rise);
297 gate->fall_time(fall);
298 gate->decay_time(decay);
299 des->add_node(gate);
300 }
301 break;
302
303 case 'X': // XNOR
304 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
305 NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
76e2c509 »
2000-10-07 Put logic devices into scopes.
306 3, NetLogic::XNOR);
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
307 connect(gate->pin(1), lsig->pin(idx));
308 connect(gate->pin(2), rsig->pin(idx));
309 connect(gate->pin(0), osig->pin(idx));
310 gate->rise_time(rise);
311 gate->fall_time(fall);
312 gate->decay_time(decay);
313 des->add_node(gate);
314 }
315 break;
316
317 case '&': // AND
318 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
319 NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
76e2c509 »
2000-10-07 Put logic devices into scopes.
320 3, NetLogic::AND);
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
321 connect(gate->pin(1), lsig->pin(idx));
322 connect(gate->pin(2), rsig->pin(idx));
323 connect(gate->pin(0), osig->pin(idx));
324 gate->rise_time(rise);
325 gate->fall_time(fall);
326 gate->decay_time(decay);
327 des->add_node(gate);
328 }
329 break;
330
331 case '|': // Bitwise OR
332 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
333 NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
b354cf68 »
2000-02-16 Fix up width matching in structural bitwise operators.
334 3, NetLogic::OR);
335 connect(gate->pin(1), lsig->pin(idx));
336 connect(gate->pin(2), rsig->pin(idx));
337 connect(gate->pin(0), osig->pin(idx));
338 gate->rise_time(rise);
339 gate->fall_time(fall);
340 gate->decay_time(decay);
341 des->add_node(gate);
342 }
343 break;
344
345 default:
346 assert(0);
347 }
348
349
350 return osig;
351 }
352
353 /*
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
354 * Elaborate the various binary comparison operators. The comparison
355 * operators return a single bit result, no matter what, so the left
356 * and right values can have their own size. The only restriction is
357 * that they have the same size.
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
358 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
359 NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
360 unsigned lwidth,
361 unsigned long rise,
362 unsigned long fall,
363 unsigned long decay) const
364 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
365 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
366 *rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
367 if (lsig == 0) {
368 cerr << get_line() << ": error: Cannot elaborate ";
369 left_->dump(cerr);
370 cerr << endl;
371 return 0;
372 }
373 if (rsig == 0) {
374 cerr << get_line() << ": error: Cannot elaborate ";
375 right_->dump(cerr);
376 cerr << endl;
377 return 0;
378 }
379
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
380 unsigned dwidth = lsig->pin_count();
381 if (rsig->pin_count() > dwidth) dwidth = rsig->pin_count();
382
383 NetNet*zero = 0;
384 if (lsig->pin_count() != rsig->pin_count()) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
385 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
386 verinum::V0);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
387 des->add_node(tmp);
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
388 zero = new NetNet(scope, scope->local_hsymbol(), NetNet::WIRE);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
389 connect(tmp->pin(0), zero->pin(0));
390 }
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
391
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
392 NetNet*osig = new NetNet(scope, scope->local_hsymbol(), NetNet::WIRE);
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
393 osig->local_flag(true);
394
395 NetNode*gate;
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
396 //NetNode*gate_t;
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
397
398 switch (op_) {
513ade9b »
1999-11-14 Support combinatorial comparators.
399 case '<':
400 case '>':
401 case 'L':
402 case 'G': {
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
403 NetCompare*cmp = new
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
404 NetCompare(scope, scope->local_hsymbol(), dwidth);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
405 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
513ade9b »
1999-11-14 Support combinatorial comparators.
406 connect(cmp->pin_DataA(idx), lsig->pin(idx));
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
407 for (unsigned idx = lsig->pin_count(); idx < dwidth ; idx += 1)
408 connect(cmp->pin_DataA(idx), zero->pin(0));
409 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
513ade9b »
1999-11-14 Support combinatorial comparators.
410 connect(cmp->pin_DataB(idx), rsig->pin(idx));
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
411 for (unsigned idx = rsig->pin_count(); idx < dwidth ; idx += 1)
412 connect(cmp->pin_DataB(idx), zero->pin(0));
413
513ade9b »
1999-11-14 Support combinatorial comparators.
414 switch (op_) {
415 case '<':
416 connect(cmp->pin_ALB(), osig->pin(0));
417 break;
418 case '>':
419 connect(cmp->pin_AGB(), osig->pin(0));
420 break;
421 case 'L':
422 connect(cmp->pin_ALEB(), osig->pin(0));
423 break;
424 case 'G':
425 connect(cmp->pin_AGEB(), osig->pin(0));
426 break;
427 }
428 gate = cmp;
429 break;
430 }
431
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
432 case 'E': // Case equals (===)
b8c5aff0 »
2001-07-07 Generate !== an an inverted ===
433 case 'N': // Case equals (!==)
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
434 // The comparison generates gates to bitwise compare
435 // each pair, and AND all the comparison results.
b8c5aff0 »
2001-07-07 Generate !== an an inverted ===
436
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
437 gate = new NetLogic(scope, scope->local_hsymbol(),
f224ed3a »
2001-01-16 Fix out-of-bound pins for comparator (PR#108)
438 1+dwidth,
b8c5aff0 »
2001-07-07 Generate !== an an inverted ===
439 (op_ == 'E')? NetLogic::AND : NetLogic::NAND);
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
440 connect(gate->pin(0), osig->pin(0));
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
441 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
442 NetCaseCmp*cmp = new NetCaseCmp(scope,
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
443 scope->local_hsymbol());
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
444
445 if (idx < lsig->pin_count())
446 connect(cmp->pin(1), lsig->pin(idx));
447 else
448 connect(cmp->pin(1), zero->pin(0));
449
450 if (idx < rsig->pin_count())
451 connect(cmp->pin(2), rsig->pin(idx));
452 else
453 connect(cmp->pin(2), zero->pin(0));
454
455 connect(cmp->pin(0), gate->pin(idx+1));
456 des->add_node(cmp);
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
457
458 // Attach a label to this intermediate wire
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
459 NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
460 NetNet::WIRE);
461 tmp->local_flag(true);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
462 connect(cmp->pin(0), tmp->pin(0));
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
463 }
464 break;
465
466
467 case 'e': // ==
9b59001c »
2000-07-08 Eleminate reduction gate for 1-bit compares.
468
469 /* Handle the special case of single bit compare with a
470 single XNOR gate. This is easy and direct. */
471 if (dwidth == 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
472 gate = new NetLogic(scope, scope->local_hsymbol(),
9b59001c »
2000-07-08 Eleminate reduction gate for 1-bit compares.
473 3, NetLogic::XNOR);
474 connect(gate->pin(0), osig->pin(0));
475 connect(gate->pin(1), lsig->pin(0));
476 connect(gate->pin(2), rsig->pin(0));
477 break;
478 }
479
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
480 /* Oh well, do the general case with a NetCompare. */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
481 { NetCompare*cmp = new NetCompare(scope, scope->local_hsymbol(),
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
482 dwidth);
483 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
484
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
485 if (idx < lsig->pin_count())
486 connect(cmp->pin_DataA(idx), lsig->pin(idx));
487 else
488 connect(cmp->pin_DataA(idx), zero->pin(0));
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
489
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
490 if (idx < rsig->pin_count())
491 connect(cmp->pin_DataB(idx), rsig->pin(idx));
492 else
493 connect(cmp->pin_DataB(idx), zero->pin(0));
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
494
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
495 }
496 connect(cmp->pin_AEB(), osig->pin(0));
497 gate = cmp;
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
498 }
499 break;
500
501 case 'n': // !=
9b59001c »
2000-07-08 Eleminate reduction gate for 1-bit compares.
502
503 /* Handle the special case of single bit compare with a
504 single XOR gate. This is easy and direct. */
505 if (dwidth == 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
506 gate = new NetLogic(scope, scope->local_hsymbol(),
9b59001c »
2000-07-08 Eleminate reduction gate for 1-bit compares.
507 3, NetLogic::XOR);
508 connect(gate->pin(0), osig->pin(0));
509 connect(gate->pin(1), lsig->pin(0));
510 connect(gate->pin(2), rsig->pin(0));
511 break;
512 }
513
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
514 /* Oh well, do the general case with a NetCompare. */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
515 { NetCompare*cmp = new NetCompare(scope, scope->local_hsymbol(),
3c8d598e »
2001-09-14 Elaborate == to NetCompare instead of XNOR and AND
516 dwidth);
517 for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
518
519 if (idx < lsig->pin_count())
520 connect(cmp->pin_DataA(idx), lsig->pin(idx));
521 else
522 connect(cmp->pin_DataA(idx), zero->pin(0));
523
524 if (idx < rsig->pin_count())
525 connect(cmp->pin_DataB(idx), rsig->pin(idx));
526 else
527 connect(cmp->pin_DataB(idx), zero->pin(0));
528
529 }
530 connect(cmp->pin_ANEB(), osig->pin(0));
531 gate = cmp;
532 }
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
533 break;
534
535 default:
536 assert(0);
537 }
538
539 gate->rise_time(rise);
540 gate->fall_time(fall);
541 gate->decay_time(decay);
542 des->add_node(gate);
543
544 return osig;
545 }
546
694ff934 »
2000-04-01 Add support for integer division.
547 /*
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
548 * Elaborate a divider gate. This function create a NetDevide gate
549 * which has exactly the right sized DataA, DataB and Result ports. If
550 * the l-value is wider then the result, then pad.
694ff934 »
2000-04-01 Add support for integer division.
551 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
552 NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
694ff934 »
2000-04-01 Add support for integer division.
553 unsigned lwidth,
554 unsigned long rise,
555 unsigned long fall,
556 unsigned long decay) const
557 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
558 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
694ff934 »
2000-04-01 Add support for integer division.
559 if (lsig == 0) return 0;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
560 NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
694ff934 »
2000-04-01 Add support for integer division.
561 if (rsig == 0) return 0;
562
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
563
564 // Check the l-value width. If it is unspecified, then use the
565 // largest operand width as the l-value width. Restrict the
566 // result width to the width of the largest operand, because
567 // there is no value is excess divider.
568
569 unsigned rwidth = lwidth;
570
571 if (rwidth == 0) {
572 rwidth = lsig->pin_count();
573 if (rsig->pin_count() > rwidth)
574 rwidth = rsig->pin_count();
575
576 lwidth = rwidth;
577 }
578
579 if ((rwidth > lsig->pin_count()) && (rwidth > rsig->pin_count())) {
580 rwidth = lsig->pin_count();
581 if (rsig->pin_count() > rwidth)
582 rwidth = rsig->pin_count();
583 }
584
585 // Create a device with the calculated dimensions.
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
586 NetDivide*div = new NetDivide(scope, scope->local_hsymbol(), rwidth,
694ff934 »
2000-04-01 Add support for integer division.
587 lsig->pin_count(),
588 rsig->pin_count());
589 des->add_node(div);
590
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
591
592 // Connect the left and right inputs of the divider to the
593 // nets that are the left and right expressions.
594
694ff934 »
2000-04-01 Add support for integer division.
595 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
596 connect(div->pin_DataA(idx), lsig->pin(idx));
597 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
598 connect(div->pin_DataB(idx), rsig->pin(idx));
599
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
600
601 // Make an output signal that is the width of the l-value.
602 // Due to above calculation of rwidth, we know that the result
603 // will be no more then the l-value, so it is safe to connect
604 // all the result pins to the osig.
605
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
606 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
694ff934 »
2000-04-01 Add support for integer division.
607 NetNet::IMPLICIT, lwidth);
608 osig->local_flag(true);
609
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
610 for (unsigned idx = 0 ; idx < rwidth ; idx += 1)
694ff934 »
2000-04-01 Add support for integer division.
611 connect(div->pin_Result(idx), osig->pin(idx));
612
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
613
614 // If the lvalue is larger then the result, then pad the
615 // output with constant 0. This can happen for example in
616 // cases like this:
617 // wire [3;0] a, b;
618 // wire [7:0] r = a / b;
619
620 if (rwidth < osig->pin_count()) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
621 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
622 verinum::V0);
694ff934 »
2000-04-01 Add support for integer division.
623 des->add_node(tmp);
8ee00ec5 »
2001-01-05 Fix net division to cope with small output sizes.
624 for (unsigned idx = rwidth ; idx < osig->pin_count() ; idx += 1)
694ff934 »
2000-04-01 Add support for integer division.
625 connect(osig->pin(idx), tmp->pin(0));
626 }
627
628 return osig;
629 }
630
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
631 /*
632 * Elaborate a modulo gate.
633 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
634 NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
635 unsigned lwidth,
636 unsigned long rise,
637 unsigned long fall,
638 unsigned long decay) const
639 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
640 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0);
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
641 if (lsig == 0) return 0;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
642 NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
643 if (rsig == 0) return 0;
644
645 unsigned rwidth = lsig->pin_count();
646 if (rsig->pin_count() > rwidth)
647 rwidth = rsig->pin_count();
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
648 NetModulo*mod = new NetModulo(scope, scope->local_hsymbol(), rwidth,
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
649 lsig->pin_count(),
650 rsig->pin_count());
651 des->add_node(mod);
652
653 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
654 connect(mod->pin_DataA(idx), lsig->pin(idx));
655 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
656 connect(mod->pin_DataB(idx), rsig->pin(idx));
657
658 if (lwidth == 0) lwidth = rwidth;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
659 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
660 NetNet::IMPLICIT, lwidth);
661 osig->local_flag(true);
662
663 unsigned cnt = osig->pin_count();
664 if (cnt > rwidth) cnt = rwidth;
665
666 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
667 connect(mod->pin_Result(idx), osig->pin(idx));
668
669 /* If the lvalue is larger then the result, then pad the
670 output with constant 0. */
671 if (cnt < osig->pin_count()) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
672 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
673 verinum::V0);
89d71767 »
2000-09-17 Add support for modulus (Eric Aardoom)
674 des->add_node(tmp);
675 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
676 connect(osig->pin(idx), tmp->pin(0));
677 }
678
679 return osig;
680 }
681
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
682 NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
ced7cc6d »
1999-12-16 Structural logical or.
683 unsigned lwidth,
684 unsigned long rise,
685 unsigned long fall,
686 unsigned long decay) const
687 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
688 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
689 *rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
ced7cc6d »
1999-12-16 Structural logical or.
690 if (lsig == 0) {
691 cerr << get_line() << ": error: Cannot elaborate ";
692 left_->dump(cerr);
693 cerr << endl;
694 return 0;
695 }
696 if (rsig == 0) {
697 cerr << get_line() << ": error: Cannot elaborate ";
698 right_->dump(cerr);
699 cerr << endl;
700 return 0;
701 }
702
703 NetLogic*gate;
704 NetLogic*gate_t;
705 switch (op_) {
706 case 'a':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
707 gate = new NetLogic(scope, scope->local_hsymbol(),
76e2c509 »
2000-10-07 Put logic devices into scopes.
708 3, NetLogic::AND);
ced7cc6d »
1999-12-16 Structural logical or.
709 break;
710 case 'o':
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
711 gate = new NetLogic(scope, scope->local_hsymbol(),
76e2c509 »
2000-10-07 Put logic devices into scopes.
712 3, NetLogic::OR);
ced7cc6d »
1999-12-16 Structural logical or.
713 break;
714 default:
715 assert(0);
716 }
717 gate->rise_time(rise);
718 gate->fall_time(fall);
719 gate->decay_time(decay);
720
721 // The first OR gate returns 1 if the left value is true...
722 if (lsig->pin_count() > 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
723 gate_t = new NetLogic(scope, scope->local_hsymbol(),
ced7cc6d »
1999-12-16 Structural logical or.
724 1+lsig->pin_count(), NetLogic::OR);
725 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
726 connect(gate_t->pin(idx+1), lsig->pin(idx));
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
727
ced7cc6d »
1999-12-16 Structural logical or.
728 connect(gate->pin(1), gate_t->pin(0));
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
729
730 /* The reduced logical value is a new nexus, create a
731 temporary signal to represent it. */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
732 NetNet*tmp = new NetTmp(scope, scope->local_hsymbol());
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
733 connect(gate->pin(1), tmp->pin(0));
734
ced7cc6d »
1999-12-16 Structural logical or.
735 des->add_node(gate_t);
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
736
ced7cc6d »
1999-12-16 Structural logical or.
737 } else {
738 connect(gate->pin(1), lsig->pin(0));
739 }
740
741 // The second OR gate returns 1 if the right value is true...
742 if (rsig->pin_count() > 1) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
743 gate_t = new NetLogic(scope, scope->local_hsymbol(),
ced7cc6d »
1999-12-16 Structural logical or.
744 1+rsig->pin_count(), NetLogic::OR);
745 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
746 connect(gate_t->pin(idx+1), rsig->pin(idx));
747 connect(gate->pin(2), gate_t->pin(0));
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
748
749 /* The reduced logical value is a new nexus, create a
750 temporary signal to represent it. */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
751 NetNet*tmp = new NetTmp(scope, scope->local_hsymbol());
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
752 connect(gate->pin(2), tmp->pin(0));
753
ced7cc6d »
1999-12-16 Structural logical or.
754 des->add_node(gate_t);
2563e2b7 »
2000-03-16 Revise the VVM backend to use nexus objects so that
755
ced7cc6d »
1999-12-16 Structural logical or.
756 } else {
757 connect(gate->pin(2), rsig->pin(0));
758 }
759
760 // The output is the AND/OR of the two logic values.
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
761 NetNet*osig = new NetNet(scope, scope->local_hsymbol(), NetNet::WIRE);
ced7cc6d »
1999-12-16 Structural logical or.
762 osig->local_flag(true);
763 connect(gate->pin(0), osig->pin(0));
764 des->add_node(gate);
765 return osig;
766 }
767
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
768 NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
769 unsigned lwidth,
770 unsigned long rise,
771 unsigned long fall,
772 unsigned long decay) const
773 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
774 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
775 if (lsig == 0) return 0;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
776 NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
777 if (rsig == 0) return 0;
778
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
779 unsigned rwidth = lwidth;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
780 NetMult*mult = new NetMult(scope, scope->local_hsymbol(), rwidth,
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
781 lsig->pin_count(),
782 rsig->pin_count());
783 des->add_node(mult);
784
785 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
786 connect(mult->pin_DataA(idx), lsig->pin(idx));
787 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
788 connect(mult->pin_DataB(idx), rsig->pin(idx));
789
790 if (lwidth == 0) lwidth = rwidth;
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
791 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
792 NetNet::IMPLICIT, lwidth);
793 osig->local_flag(true);
794
795 unsigned cnt = osig->pin_count();
796 if (cnt > rwidth) cnt = rwidth;
797
798 for (unsigned idx = 0 ; idx < cnt ; idx += 1)
799 connect(mult->pin_Result(idx), osig->pin(idx));
800
801 /* If the lvalue is larger then the result, then pad the
802 output with constant 0. */
803 if (cnt < osig->pin_count()) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
804 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
805 verinum::V0);
aa8908c5 »
2000-01-13 Multiplication all the way to simulation.
806 des->add_node(tmp);
807 for (unsigned idx = cnt ; idx < osig->pin_count() ; idx += 1)
808 connect(osig->pin(idx), tmp->pin(0));
809 }
810
811 return osig;
812 }
813
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
814 NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
815 unsigned lwidth,
816 unsigned long rise,
817 unsigned long fall,
818 unsigned long decay) const
819 {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
820 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
821 if (lsig == 0) return 0;
822
9e5ff89e »
2000-01-02 Add structural reduction NAND,
823 if (lsig->pin_count() > lwidth)
824 lwidth = lsig->pin_count();
825
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
826 /* Handle the special case of a constant shift amount. There
827 is no reason in this case to create a gate at all, just
828 connect the lsig to the osig with the bit positions
829 shifted. */
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
830 if (verinum*rval = right_->eval_const(des, scope)) {
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
831 assert(rval->is_defined());
832 unsigned dist = rval->as_ulong();
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
833 if (dist > lwidth)
834 dist = lwidth;
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
835
836 /* Very special case, constant 0 shift. */
837 if (dist == 0) return lsig;
838
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
839 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
840 NetNet::WIRE, lwidth);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
841 osig->local_flag(true);
842
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
843 NetConst*zero = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
844 verinum::V0);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
845 des->add_node(zero);
846
847 if (op_ == 'l') {
848 unsigned idx;
849 for (idx = 0 ; idx < dist ; idx += 1)
850 connect(osig->pin(idx), zero->pin(0));
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
851 for ( ; (idx<lwidth) && ((idx-dist) < lsig->pin_count())
852 ; idx += 1)
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
853 connect(osig->pin(idx), lsig->pin(idx-dist));
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
854 for ( ; idx < lwidth ; idx += 1)
855 connect(osig->pin(idx), zero->pin(0));
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
856
857 } else {
858 assert(op_ == 'r');
859 unsigned idx;
860 unsigned keep = lsig->pin_count()-dist;
861 for (idx = 0 ; idx < keep ; idx += 1)
862 connect(osig->pin(idx), lsig->pin(idx+dist));
41242735 »
2001-01-24 Handle some special cases of unary 2's complement,
863 for (idx = keep ; idx < lwidth ; idx += 1)
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
864 connect(osig->pin(idx), zero->pin(0));
865 }
866
867 return osig;
868 }
869
9e5ff89e »
2000-01-02 Add structural reduction NAND,
870 // Calculate the number of useful bits for the shift amount,
871 // and elaborate the right_ expression as the shift amount.
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
872 unsigned dwid = 0;
9e5ff89e »
2000-01-02 Add structural reduction NAND,
873 while ((1 << dwid) < lwidth)
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
874 dwid += 1;
875
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
876 NetNet*rsig = right_->elaborate_net(des, scope, dwid, 0, 0, 0);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
877 if (rsig == 0) return 0;
878
9e5ff89e »
2000-01-02 Add structural reduction NAND,
879 // Make the shift device itself, and the output
880 // NetNet. Connect the Result output pins to the osig signal
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
881 NetCLShift*gate = new NetCLShift(scope, scope->local_hsymbol(),
9e5ff89e »
2000-01-02 Add structural reduction NAND,
882 lwidth, rsig->pin_count());
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
883
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
884 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
9e5ff89e »
2000-01-02 Add structural reduction NAND,
885 NetNet::WIRE, lwidth);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
886 osig->local_flag(true);
887
9e5ff89e »
2000-01-02 Add structural reduction NAND,
888 for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
889 connect(osig->pin(idx), gate->pin_Result(idx));
9e5ff89e »
2000-01-02 Add structural reduction NAND,
890
891 // Connect the lsig (the left expression) to the Data input,
892 // and pad it if necessary with constant zeros.
893 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
894 connect(lsig->pin(idx), gate->pin_Data(idx));
9e5ff89e »
2000-01-02 Add structural reduction NAND,
895
896 if (lsig->pin_count() < lwidth) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
897 NetConst*zero = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
898 verinum::V0);
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
899 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol());
9e5ff89e »
2000-01-02 Add structural reduction NAND,
900 des->add_node(zero);
ba7fdb58 »
2000-01-02 Add a signal to nexus of padding constant.
901 connect(zero->pin(0), tmp->pin(0));
9e5ff89e »
2000-01-02 Add structural reduction NAND,
902 for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
903 connect(zero->pin(0), gate->pin_Data(idx));
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
904 }
905
9e5ff89e »
2000-01-02 Add structural reduction NAND,
906 // Connect the rsig (the shift amount expression) to the
907 // Distance input.
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
908 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
909 connect(rsig->pin(idx), gate->pin_Distance(idx));
910
911 if (op_ == 'r') {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
912 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol());
913 NetConst*dir = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
914 verinum::V1);
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
915 connect(dir->pin(0), gate->pin_Direction());
ca6631fd »
2000-05-07 Fix connection of Direction of LMP_CLSHIFT
916 connect(tmp->pin(0), gate->pin_Direction());
1624afe1 »
1999-11-14 Add support for the LPM_CLSHIFT device.
917 des->add_node(dir);
918 }
919
920 des->add_node(gate);
921
922 return osig;
923 }
924
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
925 /*
926 * The concatenation operator, as a net, is a wide signal that is
927 * connected to all the pins of the elaborated expression nets.
928 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
929 NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
930 unsigned,
931 unsigned long rise,
932 unsigned long fall,
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
933 unsigned long decay,
934 Link::strength_t drive0,
935 Link::strength_t drive1) const
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
936 {
937 svector<NetNet*>nets (parms_.count());
938 unsigned pins = 0;
939 unsigned errors = 0;
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
940 unsigned repeat = 1;
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
941
942 if (repeat_) {
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
943 verinum*rep = repeat_->eval_const(des, scope);
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
944 if (rep == 0) {
945 cerr << get_line() << ": internal error: Unable to "
946 << "evaluate constant repeat expression." << endl;
947 des->errors += 1;
948 return 0;
949 }
950
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
951 repeat = rep->as_ulong();
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
952
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
953 if (repeat == 0) {
954 cerr << get_line() << ": error: Invalid repeat value."
955 << endl;
956 des->errors += 1;
957 delete rep;
958 return 0;
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
959 }
960 }
961
962 /* Elaborate the operands of the concatenation. */
963 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
79b1c51e »
2000-09-26 Detect indefinite widths where definite widths are required.
964
f526d235 »
2000-10-14 Check for missing concat subexpressions (PR#11)
965 if (parms_[idx] == 0) {
966 cerr << get_line() << ": error: Empty expressions "
967 << "not allowed in concatenations." << endl;
968 errors += 1;
969 continue;
970 }
971
79b1c51e »
2000-09-26 Detect indefinite widths where definite widths are required.
972 /* Look for the special case of an unsized number in a
973 concatenation expression. Mark this as an error, but
974 allow elaboration to continue to see if I can find
975 more errors. */
976
977 if (PENumber*tmp = dynamic_cast<PENumber*>(parms_[idx])) {
978 if (tmp->value().has_len() == false) {
979 cerr << get_line() << ": error: Number "
980 << tmp->value() << " with indefinite size"
981 << " in concatenation." << endl;
982 errors += 1;
983 }
984 }
985
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
986 nets[idx] = parms_[idx]->elaborate_net(des, scope, 0,
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
987 rise,fall,decay);
988 if (nets[idx] == 0)
989 errors += 1;
990 else
991 pins += nets[idx]->pin_count();
992 }
993
994 /* If any of the sub expressions failed to elaborate, then
995 delete all those that did and abort myself. */
996 if (errors) {
997 for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
998 if (nets[idx]) delete nets[idx];
999 }
1000 des->errors += 1;
1001 return 0;
1002 }
1003
1004 /* Make the temporary signal that connects to all the
1005 operands, and connect it up. Scan the operands of the
1006 concat operator from least significant to most significant,
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
1007 which is opposite from how they are given in the list.
1008
1009 Allow for a repeat count other then 1 by repeating the
1010 connect loop as many times as necessary. */
1011
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1012 NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
1013 NetNet::IMPLICIT, pins * repeat);
1014
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
1015 pins = 0;
4819d54d »
2000-10-08 Fix repeat concatenation with multiple expressions (PR#10)
1016 for (unsigned rpt = 0 ; rpt < repeat ; rpt += 1)
1017 for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
1018 NetNet*cur = nets[idx-1];
1019 for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
1020 connect(osig->pin(pins), cur->pin(pin));
1021 pins += 1;
1022 }
cdb99e76 »
1999-12-02 Elaborate net repeat concatenations.
1023 }
1024
1025 osig->local_flag(true);
1026 return osig;
1027 }
1028
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1029 NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1030 unsigned lwidth,
1031 unsigned long rise,
1032 unsigned long fall,
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
1033 unsigned long decay,
1034 Link::strength_t drive0,
1035 Link::strength_t drive1) const
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1036 {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1037 NetNet*sig = des->find_signal(scope, path_);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1038
1039 if (sig == 0) {
1040 /* If the identifier is a memory instead of a signal,
1041 then handle it elsewhere. Create a RAM. */
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1042 if (NetMemory*mem = des->find_memory(scope, path_))
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1043 return elaborate_net_ram_(des, scope, mem, lwidth,
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1044 rise, fall, decay);
1045
1046
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1047 if (const NetExpr*pe = des->find_parameter(scope, path_)) {
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1048
1049 const NetEConst*pc = dynamic_cast<const NetEConst*>(pe);
1050 assert(pc);
1051 verinum pvalue = pc->value();
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1052 sig = new NetNet(scope,
1053 scope->name()+"."+path_.peek_name(0),
1054 NetNet::IMPLICIT, pc->expr_width());
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1055 NetConst*cp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
1056 pvalue);
65ae9285 »
1999-12-17 NetConst can now hold wide constants.
1057 des->add_node(cp);
1058 for (unsigned idx = 0; idx < sig->pin_count(); idx += 1)
1059 connect(sig->pin(idx), cp->pin(idx));
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1060
1061 } else {
1062
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1063 sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
1064 NetNet::IMPLICIT, 1);
48de7395 »
2000-03-17 Switch to control warnings.
1065
1066 if (warn_implicit)
1067 cerr << get_line() << ": warning: implicit "
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1068 "definition of wire " << scope->name()
1069 << "." << path_ << "." << endl;
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1070 }
1071 }
1072
1073 assert(sig);
1074
1075 if (msb_ && lsb_) {
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1076 verinum*mval = msb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1077 if (mval == 0) {
1078 cerr << msb_->get_line() << ": error: unable to "
1079 "evaluate constant expression: " << *msb_ <<
1080 endl;
1081 des->errors += 1;
1082 return 0;
1083 }
1084
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1085 verinum*lval = lsb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1086 if (lval == 0) {
1087 cerr << lsb_->get_line() << ": error: unable to "
1088 "evaluate constant expression: " << *lsb_ <<
1089 endl;
1090 delete mval;
1091 des->errors += 1;
1092 return 0;
1093 }
1094
1095 assert(mval);
1096 assert(lval);
1097 unsigned midx = sig->sb_to_idx(mval->as_long());
1098 unsigned lidx = sig->sb_to_idx(lval->as_long());
1099
2a08824a »
2000-07-15 Detect muxing Vz as a bufufN.
1100 /* This is a part select, create a new NetNet object
1101 that connects to just the desired parts of the
1102 identifier. Make sure the NetNet::Type is compatible
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1103 with the sig type.
1104
1105 Be careful to check the bit ordering. If the msb is
1106 less significant then the msb, then the source is
1107 broken. I can hack it in order to go on, but report
1108 an error. */
1109
1110 if (midx < lidx) {
1111 cerr << get_line() << ": error: part select "
1112 << sig->name() << "[" << mval->as_long() << ":"
1113 << lval->as_long() << "] "
1114 << "has bit order reversed." << endl;
1115 des->errors += 1;
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1116
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1117 unsigned tmp = midx;
1118 midx = lidx;
1119 lidx = tmp;
1120 }
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1121
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1122 NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1123 sig->type(), midx-lidx+1);
1124 tmp->local_flag(true);
2b903f5d »
2001-02-09 Detect part select out of range in nets. (PR#138)
1125
1126 /* Check that the bit or part select of the signal is
1127 within the range of the part. The lidx is the
1128 normalized index of the LSB, so that plus the desired
1129 width must be <= the width of the references signal. */
1130 if ((lidx + tmp->pin_count()) > sig->pin_count()) {
1131 cerr << get_line() << ": error: bit/part select ["
1132 << mval->as_long() << ":" << lval->as_long()
1133 << "] out of range for " << sig->name() << endl;
1134 des->errors += 1;
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1135 return sig;
1136 }
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1137
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1138 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1139 connect(tmp->pin(idx-lidx), sig->pin(idx));
2a08824a »
2000-07-15 Detect muxing Vz as a bufufN.
1140
f2997d77 »
2000-10-30 Detect reverse bit order in part select. (PR#33)
1141 sig = tmp;
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1142
1143
1144 } else if (msb_) {
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1145 verinum*mval = msb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1146 if (mval == 0) {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1147 cerr << get_line() << ": error: index of " << path_ <<
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1148 " needs to be constant in this context." <<
1149 endl;
1150 des->errors += 1;
1151 return 0;
1152 }
1153 assert(mval);
1154 unsigned idx = sig->sb_to_idx(mval->as_long());
1155 if (idx >= sig->pin_count()) {
3ce86f56 »
2001-05-17 Make error message include error: prefix.
1156 cerr << get_line() << ": error: index " << sig->name() <<
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1157 "[" << mval->as_long() << "] out of range." << endl;
1158 des->errors += 1;
1159 idx = 0;
1160 }
2a08824a »
2000-07-15 Detect muxing Vz as a bufufN.
1161
1162 /* This is a bit select, create a compatible NetNet with
1163 a single bit that links to the selected bit of the
1164 expression. */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1165 NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
2a08824a »
2000-07-15 Detect muxing Vz as a bufufN.
1166 sig->type(), 1);
1167 tmp->local_flag(true);
1168
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1169 connect(tmp->pin(0), sig->pin(idx));
1170 sig = tmp;
1171 }
1172
1173 return sig;
1174 }
1175
1176 /*
1177 * When I run into an identifier in an expression that referrs to a
1178 * memory, create a RAM port object.
1179 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1180 NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1181 NetMemory*mem, unsigned lwidth,
1182 unsigned long rise,
1183 unsigned long fall,
1184 unsigned long decay) const
1185 {
8d8f1e24 »
2000-05-02 Move signal tables to the NetScope class.
1186 assert(scope);
1187
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1188 if (msb_ == 0) {
1189 cerr << get_line() << ": error: memory reference without"
1190 " the required index expression." << endl;
1191 des->errors += 1;
1192 return 0;
1193 }
1194
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1195 NetNet*adr = msb_->elaborate_net(des, scope, 0, 0, 0, 0);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1196 if (adr == 0)
1197 return 0;
1198
1199
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
1200 NetRamDq*ram = new NetRamDq(scope, des->local_symbol(mem->name()),
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1201 mem, adr->pin_count());
1202 des->add_node(ram);
1203
1204 for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
1205 connect(ram->pin_Address(idx), adr->pin(idx));
1206
eeabc723 »
2001-07-01 Make sure tmp net gets connected to ramdq output
1207 NetNet*osig = new NetNet(scope, des->local_symbol(mem->name()),
1208 NetNet::IMPLICIT, ram->width());
1209 osig->local_flag(true);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1210
1211 for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
1212 connect(ram->pin_Q(idx), osig->pin(idx));
1213
1214 return osig;
1215 }
1216
1217 /*
1218 * Identifiers in continuous assignment l-values are limited to wires
1219 * and that ilk. Detect registers and memories here and report errors.
1220 */
6bfbcbdc »
2001-11-07 elaborate_lnet uses scope instead of string path.
1221 NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1222 {
6bfbcbdc »
2001-11-07 elaborate_lnet uses scope instead of string path.
1223 string path = scope->name();
8d8f1e24 »
2000-05-02 Move signal tables to the NetScope class.
1224
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1225 NetNet*sig = des->find_signal(scope, path_);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1226 if (sig == 0) {
1227 /* Don't allow memories here. Is it a memory? */
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1228 if (des->find_memory(scope, path_)) {
1229 cerr << get_line() << ": error: memories (" << path_
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1230 << ") cannot be l-values in continuous "
1231 << "assignments." << endl;
1232 return 0;
1233 }
1234
1235 /* Fine, create an implicit wire as an l-value. */
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1236 sig = new NetNet(scope, path+"."+path_.peek_name(0),
1237 NetNet::IMPLICIT, 1);
48de7395 »
2000-03-17 Switch to control warnings.
1238
1239 if (warn_implicit)
1240 cerr << get_line() << ": warning: implicit "
1241 " definition of wire " << path << "." <<
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1242 path_.peek_name(0) << "." << endl;
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1243 }
1244
1245 assert(sig);
1246
1247 /* Don't allow registers as assign l-values. */
1248 if (sig->type() == NetNet::REG) {
1249 cerr << get_line() << ": error: registers (" << sig->name()
1250 << ") cannot be l-values in continuous"
1251 << " assignments." << endl;
1252 return 0;
1253 }
1254
4d0b840c »
2001-11-10 Coerse input to inout when assigned to.
1255 if (sig->port_type() == NetNet::PINPUT) {
1256 cerr << get_line() << ": warning: assign l-value ``"
1257 << sig->name() << "'' is also an input to "
1258 << sig->scope()->name() << "." << endl;
1259 cerr << sig->get_line() << ": warning: input ``"
1260 << sig->name() << "'' is coerced to inout." << endl;
1261 sig->port_type(NetNet::PINOUT);
1262 }
1263
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1264 if (msb_ && lsb_) {
1265 /* Detect a part select. Evaluate the bits and elaborate
1266 the l-value by creating a sub-net that links to just
1267 the right pins. */
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1268 verinum*mval = msb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1269 assert(mval);
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1270 verinum*lval = lsb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1271 assert(lval);
1272 unsigned midx = sig->sb_to_idx(mval->as_long());
1273 unsigned lidx = sig->sb_to_idx(lval->as_long());
1274
1275 if (midx >= lidx) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1276 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1277 midx-lidx+1);
1278 if (tmp->pin_count() > sig->pin_count()) {
1279 cerr << get_line() << ": bit select out of "
1280 << "range for " << sig->name() << endl;
1281 return sig;
1282 }
1283
1284 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1285 connect(tmp->pin(idx-lidx), sig->pin(idx));
1286
1287 sig = tmp;
1288
1289 } else {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1290 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1291 lidx-midx+1);
4eed86d5 »
2000-12-01 Detect part select errors on l-values.
1292
1293 if (tmp->pin_count() > sig->pin_count()) {
1294 cerr << get_line() << ": error: "
1295 << "part select out of range for "
1296 << sig->name() << "." << endl;
1297 des->errors += 1;
1298 return sig;
1299 }
1300
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1301 assert(tmp->pin_count() <= sig->pin_count());
1302 for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
1303 connect(tmp->pin(idx-midx), sig->pin(idx));
1304
1305 sig = tmp;
1306 }
1307
1308 } else if (msb_) {
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1309 verinum*mval = msb_->eval_const(des, scope);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1310 if (mval == 0) {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1311 cerr << get_line() << ": error: index of " << path_ <<
ac81f6a2 »
2000-09-02 Rearrange NetAssign to make NetAssign_ separate.
1312 " needs to be constant in l-value of assignment." <<
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1313 endl;
1314 des->errors += 1;
1315 return 0;
1316 }
1317 assert(mval);
1318 unsigned idx = sig->sb_to_idx(mval->as_long());
1319 if (idx >= sig->pin_count()) {
1320 cerr << get_line() << "; index " << sig->name() <<
1321 "[" << mval->as_long() << "] out of range." << endl;
1322 des->errors += 1;
1323 idx = 0;
1324 }
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1325 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(), 1);
a81dcd79 »
1999-11-21 Support memories in continuous assignments.
1326 connect(tmp->pin(0), sig->pin(idx));
1327 sig = tmp;
1328 }
1329
1330 return sig;
1331 }
1332
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
1333 /*
3676d664 »
2000-05-16 Module ports are really special PEIdent
1334 * This method is used to elaborate identifiers that are ports to a
1335 * scope. The scope is presumed to be that of the module that has the
1336 * port.
1337 */
1338 NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
1339 {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1340 NetNet*sig = des->find_signal(scope, path_);
3676d664 »
2000-05-16 Module ports are really special PEIdent
1341 if (sig == 0) {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1342 cerr << get_line() << ": error: no wire/reg " << path_
3676d664 »
2000-05-16 Module ports are really special PEIdent
1343 << " in module " << scope->name() << "." << endl;
1344 des->errors += 1;
1345 return 0;
1346 }
1347
a59bbdeb »
2000-08-18 Proper error messages when port direction is missing.
1348 switch (sig->port_type()) {
1349 case NetNet::PINPUT:
1350 case NetNet::POUTPUT:
1351 case NetNet::PINOUT:
1352 break;
1353
1354 /* If the name matches, but the signal is not a port,
1355 then the user declared the object but there is no
1356 matching input/output/inout declaration. */
1357
1358 case NetNet::NOT_A_PORT:
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1359 cerr << get_line() << ": error: signal " << path_ << " in"
a59bbdeb »
2000-08-18 Proper error messages when port direction is missing.
1360 << " module " << scope->name() << " is not a port." << endl;
1361 cerr << get_line() << ": : Are you missing an input/"
1362 << "output/inout declaration?" << endl;
1363 des->errors += 1;
1364 return 0;
1365
1366 /* This should not happen. A PWire can only become
1367 PIMPLICIT if this is a udp reg port, and the make_udp
1368 function should turn it into an output.... I think. */
1369
1370 case NetNet::PIMPLICIT:
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1371 cerr << get_line() << ": internal error: signal " << path_
a59bbdeb »
2000-08-18 Proper error messages when port direction is missing.
1372 << " in module " << scope->name() << " is left as "
1373 << "port type PIMPLICIT." << endl;
1374 des->errors += 1;
1375 return 0;
1376 }
1377
3676d664 »
2000-05-16 Module ports are really special PEIdent
1378
1379 if (msb_ && lsb_) {
1380 /* Detect a part select. Evaluate the bits and elaborate
1381 the l-value by creating a sub-net that links to just
1382 the right pins. */
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1383 verinum*mval = msb_->eval_const(des, scope);
3676d664 »
2000-05-16 Module ports are really special PEIdent
1384 assert(mval);
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1385 verinum*lval = lsb_->eval_const(des, scope);
3676d664 »
2000-05-16 Module ports are really special PEIdent
1386 assert(lval);
1387 unsigned midx = sig->sb_to_idx(mval->as_long());
1388 unsigned lidx = sig->sb_to_idx(lval->as_long());
1389
1390 if (midx >= lidx) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1391 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
3676d664 »
2000-05-16 Module ports are really special PEIdent
1392 midx-lidx+1);
1393 if (tmp->pin_count() > sig->pin_count()) {
1394 cerr << get_line() << ": bit select out of "
1395 << "range for " << sig->name() << endl;
1396 return sig;
1397 }
1398
1399 for (unsigned idx = lidx ; idx <= midx ; idx += 1)
1400 connect(tmp->pin(idx-lidx), sig->pin(idx));
1401
1402 sig = tmp;
1403
1404 } else {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1405 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
3676d664 »
2000-05-16 Module ports are really special PEIdent
1406 lidx-midx+1);
1407 assert(tmp->pin_count() <= sig->pin_count());
1408 for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
1409 connect(tmp->pin(idx-midx), sig->pin(idx));
1410
1411 sig = tmp;
1412 }
1413
1414 } else if (msb_) {
bf72f39f »
2001-11-07 eval_const uses scope instead of a string path.
1415 verinum*mval = msb_->eval_const(des, scope);
3676d664 »
2000-05-16 Module ports are really special PEIdent
1416 if (mval == 0) {
ab6c8cb4 »
2001-12-03 Parser and pform use hierarchical names as hname_t
1417 cerr << get_line() << ": index of " << path_ <<
ac81f6a2 »
2000-09-02 Rearrange NetAssign to make NetAssign_ separate.
1418 " needs to be constant in port context." <<
3676d664 »
2000-05-16 Module ports are really special PEIdent
1419 endl;
1420 des->errors += 1;
1421 return 0;
1422 }
1423 assert(mval);
1424 unsigned idx = sig->sb_to_idx(mval->as_long());
1425 if (idx >= sig->pin_count()) {
1426 cerr << get_line() << "; index " << sig->name() <<
1427 "[" << mval->as_long() << "] out of range." << endl;
1428 des->errors += 1;
1429 idx = 0;
1430 }
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1431 NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(), 1);
3676d664 »
2000-05-16 Module ports are really special PEIdent
1432 connect(tmp->pin(0), sig->pin(idx));
1433 sig = tmp;
1434 }
1435
1436 return sig;
1437 }
1438
1439
1440 /*
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
1441 * Elaborate a number as a NetConst object.
1442 */
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1443 NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
1444 unsigned lwidth,
1445 unsigned long rise,
1446 unsigned long fall,
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
1447 unsigned long decay,
1448 Link::strength_t drive0,
1449 Link::strength_t drive1) const
206b37e5 »
1999-11-05 Fix NetConst being set to zero width, and clean
1450 {
8d8f1e24 »
2000-05-02 Move signal tables to the NetScope class.
1451
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1452 /* If we are constrained by a l-value size, then just make a
1453 number constant with the correct size and set as many bits
1454 in that constant as make sense. Pad excess with zeros. */
1455 if (lwidth > 0) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1456 NetNet*net = new NetNet(scope, scope->local_hsymbol(),
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1457 NetNet::IMPLICIT, lwidth);
1458 net->local_flag(true);
1459
60c2046b »
2000-08-01 Extend x or z that is top bit of a constant.
1460 /* when expanding a constant to fit into the net, extend
1461 the Vx or Vz values if they are in the sign position,
1462 otherwise extend the number with 0 bits. */
1463 verinum::V top_v = verinum::V0;
1464 switch (value_->get(value_->len()-1)) {
1465 case verinum::Vx:
1466 top_v = verinum::Vx;
1467 break;
1468 case verinum::Vz:
1469 top_v = verinum::Vz;
1470 break;
1471 }
1472
1473 verinum num(top_v, net->pin_count());
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1474 unsigned idx;
1475 for (idx = 0 ; idx < num.len() && idx < value_->len(); idx += 1)
1476 num.set(idx, value_->get(idx));
1477
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1478 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
1479 num);
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
1480 for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
1481 tmp->pin(idx).drive0(drive0);
1482 tmp->pin(idx).drive1(drive1);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1483 connect(net->pin(idx), tmp->pin(idx));
b90cda1f »
2000-05-07 Carry strength values from Verilog source to the
1484 }
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1485
1486 des->add_node(tmp);
1487 return net;
1488 }
1489
1490 /* If the number has a length, then use that to size the
1491 number. Generate a constant object of exactly the user
1492 specified size. */
1493 if (value_->has_len()) {
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1494 NetNet*net = new NetNet(scope, scope->local_hsymbol(),
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1495 NetNet::IMPLICIT, value_->len());
1496 net->local_flag(true);
7793a498 »
2001-11-08 Remove string paths from PExpr elaboration.
1497 NetConst*tmp = new NetConst(scope, scope->local_hsymbol(),
874bab10 »
2001-10-28 NetObj constructor finally requires a scope.
1498 *value_);
3d1ffced »
2000-01-11 Elaborate net widths of constants to as small
1499 for (unsigned idx = 0 ; idx < value_->len() ; idx += 1)
1500 connect(net->pin(idx), tmp->pin(idx));
1501
1502 des->add_node(tmp);
1503