Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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