Skip to content
Newer
Older
100644 3710 lines (3112 sloc) 111 KB
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
1 /*
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
2 * Copyright (c) 1999-2008 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);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
73 case 'p': // **
74 return elaborate_net_pow_(des, scope, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
75 case '+':
76 case '-':
7793a49 Remove string paths from PExpr elaboration.
steve authored
77 return elaborate_net_add_(des, scope, width, rise, fall, decay);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
78 case '|': // Bitwise OR
79 case '&':
80 case '^':
dac99b9 Add support for binary nand operator.
steve authored
81 case 'A': // Bitwise NAND (~&)
3d3116d Add support for binary NOR operator.
steve authored
82 case 'O': // Bitwise NOR (~|)
8f0c02c Spelling fixes.
steve authored
83 case 'X': // Exclusive NOR
7793a49 Remove string paths from PExpr elaboration.
steve authored
84 return elaborate_net_bit_(des, scope, width, rise, fall, decay);
b8c5aff Generate !== an an inverted ===
steve authored
85 case 'E': // === (case equals)
86 case 'e': // ==
87 case 'N': // !== (case not-equals)
88 case 'n': // !=
513ade9 Support combinatorial comparators.
steve authored
89 case '<':
90 case '>':
91 case 'L': // <=
92 case 'G': // >=
7793a49 Remove string paths from PExpr elaboration.
steve authored
93 return elaborate_net_cmp_(des, scope, width, rise, fall, decay);
ced7cc6 Structural logical or.
steve authored
94 case 'a': // && (logical and)
95 case 'o': // || (logical or)
7793a49 Remove string paths from PExpr elaboration.
steve authored
96 return elaborate_net_log_(des, scope, width, rise, fall, decay);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
97 case 'l': // <<
98 case 'r': // >>
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
99 case 'R': // >>>
7793a49 Remove string paths from PExpr elaboration.
steve authored
100 return elaborate_net_shift_(des, scope, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
101 }
102
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
103 /* This is an undefined operator, but we may as well check the
104 arguments since we are here. */
7793a49 Remove string paths from PExpr elaboration.
steve authored
105 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
106 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
107 if (lsig == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
108 cerr << get_fileline() << ": error: Cannot elaborate ";
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
109 left_->dump(cerr);
110 cerr << endl;
111 }
112 if (rsig == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
113 cerr << get_fileline() << ": error: Cannot elaborate ";
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
114 right_->dump(cerr);
115 cerr << endl;
116 }
117
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
118 /* We can only get here with an undefined operator. */
119 cerr << get_fileline() << ": internal error: unsupported"
120 " combinational operator (" << op_ << ")." << endl;
121 des->errors += 1;
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
122
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
123 return 0;
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
124 }
125
126 /*
127 * Elaborate the structural +/- as an AddSub object. Connect DataA and
128 * DataB to the parameters, and connect the output signal to the
129 * Result. In this context, the device is a combinational adder with
130 * fixed direction, so leave Add_Sub unconnected and set the
131 * LPM_Direction property.
132 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
133 NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
134 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
135 const NetExpr* rise,
136 const NetExpr* fall,
137 const NetExpr* decay) const
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
138 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
139 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
140 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
141
142 if (lsig == 0 || rsig == 0) return 0;
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
143
144 NetNet*osig;
145
75ad905 Generalize signals to carry types.
steve authored
146 unsigned width = lsig->vector_width();
147 if (rsig->vector_width() > lsig->vector_width())
148 width = rsig->vector_width();
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
149
d78c739 Remove dead code.
steve authored
150
4124273 Handle some special cases of unary 2's complement,
steve authored
151 /* The owidth is the output width of the lpm_add_sub
d9ac146 @ldoolitt Spelling fixes
ldoolitt authored
152 device. If the desired width is greater than the width of
4124273 Handle some special cases of unary 2's complement,
steve authored
153 the operands, then widen the adder and let code below pad
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
154 the operands. */
4124273 Handle some special cases of unary 2's complement,
steve authored
155 unsigned owidth = width;
156 switch (op_) {
157 case '+':
158 if (lwidth > owidth) {
159 owidth = lwidth;
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
160 width = lwidth;
4124273 Handle some special cases of unary 2's complement,
steve authored
161 }
162 break;
163 case '-':
164 if (lwidth > owidth) {
165 owidth = lwidth;
166 width = lwidth;
167 }
168 break;
169 default:
170 assert(0);
171 }
d78c739 Remove dead code.
steve authored
172
33a391c Sign extend operands of signed addition.
steve authored
173 bool expr_signed = lsig->get_signed() && rsig->get_signed();
d54cc14 Simulate carry output on adders.
steve authored
174
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
175 // Pad out the operands, if necessary, the match the width of
176 // the adder device.
f8d410e @ldoolitt remove lint flagged by gcc-4.3
ldoolitt authored
177 if (lsig->vector_width() < width) {
33a391c Sign extend operands of signed addition.
steve authored
178 if (expr_signed)
179 lsig = pad_to_width_signed(des, lsig, width);
180 else
181 lsig = pad_to_width(des, lsig, width);
f8d410e @ldoolitt remove lint flagged by gcc-4.3
ldoolitt authored
182 }
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
183
f8d410e @ldoolitt remove lint flagged by gcc-4.3
ldoolitt authored
184 if (rsig->vector_width() < width) {
33a391c Sign extend operands of signed addition.
steve authored
185 if (expr_signed)
186 rsig = pad_to_width_signed(des, rsig, width);
187 else
188 rsig = pad_to_width(des, rsig, width);
f8d410e @ldoolitt remove lint flagged by gcc-4.3
ldoolitt authored
189 }
acfb5c1 Over agressive signal elimination in constant probadation.
steve authored
190
75ad905 Generalize signals to carry types.
steve authored
191 // Check that the argument types match.
192 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
193 cerr << get_fileline() << ": error: Arguments of add/sub "
75ad905 Generalize signals to carry types.
steve authored
194 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
195 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
196 << lsig->data_type() << ", right argument is "
197 << rsig->data_type() << "." << endl;
198 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
199 return 0;
75ad905 Generalize signals to carry types.
steve authored
200 }
201
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
202 // Make the adder as wide as the widest operand
badad63 All NetObj objects have lex_string base names.
steve authored
203 osig = new NetNet(scope, scope->local_symbol(),
4124273 Handle some special cases of unary 2's complement,
steve authored
204 NetNet::WIRE, owidth);
75ad905 Generalize signals to carry types.
steve authored
205 osig->data_type(lsig->data_type());
33a391c Sign extend operands of signed addition.
steve authored
206 osig->set_signed(expr_signed);
4124273 Handle some special cases of unary 2's complement,
steve authored
207 osig->local_flag(true);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
208 osig->set_line(*this);
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
209 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
210 cerr << get_fileline() << ": debug: Elaborate NetAddSub "
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
211 << "width=" << width << " lwidth=" << lwidth
212 << endl;
213 }
badad63 All NetObj objects have lex_string base names.
steve authored
214 NetAddSub*adder = new NetAddSub(scope, scope->local_symbol(), width);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
215
216 // Connect the adder to the various parts.
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
217 connect(lsig->pin(0), adder->pin_DataA());
218 connect(rsig->pin(0), adder->pin_DataB());
219 connect(osig->pin(0), adder->pin_Result());
220 #ifdef XXXX
d54cc14 Simulate carry output on adders.
steve authored
221 if (owidth > width)
222 connect(osig->pin(width), adder->pin_Cout());
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
223 #endif
61195c5 Harmless fixup of warnings.
steve authored
224 NetNode*gate = adder;
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
225 gate->set_line(*this);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
226 gate->rise_time(rise);
227 gate->fall_time(fall);
228 gate->decay_time(decay);
229 des->add_node(gate);
230
9ee0210 Code cleanup from Larry.
steve authored
231 gate->attribute(perm_string::literal("LPM_Direction"),
232 verinum(op_ == '+' ? "ADD" : "SUB"));
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
233
234 return osig;
235 }
236
237 /*
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
238 * Elaborate various bitwise logic operators. These are all similar in
239 * that they take operants of equal width, and each bit does not
240 * affect any other bits. Also common about all this is how bit widths
241 * of the operands are handled, when they do not match.
242 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
243 NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
244 unsigned width,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
245 const NetExpr* rise,
246 const NetExpr* fall,
247 const NetExpr* decay) const
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
248 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
249 NetNet*lsig = left_->elaborate_net(des, scope, width, 0, 0, 0),
250 *rsig = right_->elaborate_net(des, scope, width, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
251
252 if (lsig == 0 || rsig == 0) return 0;
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
253
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
254 if (lsig->vector_width() < rsig->vector_width())
255 lsig = pad_to_width(des, lsig, rsig->vector_width());
256 if (rsig->vector_width() < lsig->vector_width())
257 rsig = pad_to_width(des, rsig, lsig->vector_width());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
258
4902c22 Check operand types for compatibility.
steve authored
259 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
260 cerr << get_fileline() << ": error: Types of "
4dfdc14 fit type elaboration of logical not.
steve authored
261 << "operands of " << op_ << " do not match: "
262 << lsig->data_type() << " vs. " << rsig->data_type()
4902c22 Check operand types for compatibility.
steve authored
263 << endl;
264 des->errors += 1;
265 return 0;
266 }
267
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
268 /* The types match here and real is not supported. */
269 if (lsig->data_type() == IVL_VT_REAL) {
f4cf7b1 @ldoolitt Cleanup from yesterday's "Add more error checking" patch
ldoolitt authored
270 cerr << get_fileline() << ": error: " << human_readable_op(op_)
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
271 << " operator may not have REAL operands." << endl;
272 des->errors += 1;
273 return 0;
274 }
275
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
276 if (lsig->vector_width() != rsig->vector_width()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
277 cerr << get_fileline() << ": internal error: lsig width ("
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
278 << lsig->vector_width() << ") != rsig pin width ("
279 << rsig->vector_width() << ")." << endl;
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
280 des->errors += 1;
281 return 0;
282 }
283
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
284 assert(lsig->vector_width() == rsig->vector_width());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
285
badad63 All NetObj objects have lex_string base names.
steve authored
286 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE,
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
287 lsig->vector_width());
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
288 osig->local_flag(true);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
289 osig->set_line(*this);
4902c22 Check operand types for compatibility.
steve authored
290 osig->data_type( lsig->data_type() );
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
291
9ee0210 Code cleanup from Larry.
steve authored
292 NetLogic::TYPE gtype=NetLogic::AND;
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
293 switch (op_) {
9ee0210 Code cleanup from Larry.
steve authored
294 case '^': gtype = NetLogic::XOR; break; // XOR
295 case 'X': gtype = NetLogic::XNOR; break; // XNOR
296 case '&': gtype = NetLogic::AND; break; // AND
297 case 'A': gtype = NetLogic::NAND; break; // NAND (~&)
298 case '|': gtype = NetLogic::OR; break; // Bitwise OR
299 case 'O': gtype = NetLogic::NOR; break; // Bitwise NOR
300 default: assert(0);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
301 }
302
609b6a7 Netlist boolean expressions generate gate vectors.
steve authored
303 NetLogic*gate = new NetLogic(scope, scope->local_symbol(),
304 3, gtype, osig->vector_width());
305 gate->set_line(*this);
306 connect(gate->pin(0), osig->pin(0));
307 connect(gate->pin(1), lsig->pin(0));
308 connect(gate->pin(2), rsig->pin(0));
309 gate->rise_time(rise);
310 gate->fall_time(fall);
311 gate->decay_time(decay);
312 des->add_node(gate);
b354cf6 Fix up width matching in structural bitwise operators.
steve authored
313
314 return osig;
315 }
316
317 /*
fd371a3 Handle equality compare to constants specially.
steve authored
318 * This function attempts to handle the special case of == or !=
319 * compare to a constant value. The caller has determined already that
320 * one of the operands is a NetEConst, and has already elaborated the
321 * other.
322 */
323 static NetNet* compare_eq_constant(Design*des, NetScope*scope,
324 NetNet*lsig, NetEConst*rexp,
325 char op_code,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
326 const NetExpr* rise,
327 const NetExpr* fall,
328 const NetExpr* decay)
fd371a3 Handle equality compare to constants specially.
steve authored
329 {
330 if (op_code != 'e' && op_code != 'n')
331 return 0;
332
333 verinum val = rexp->value();
334
335 /* Abandon special case if there are x or z bits in the
336 constant. We can't get the right behavior out of
337 OR/NOR in this case. */
338 if (! val.is_defined())
339 return 0;
340
ead2481 Fix elaboration of == compared to constants.
steve authored
341 if (val.len() < lsig->vector_width())
342 val = verinum(val, lsig->vector_width());
fd371a3 Handle equality compare to constants specially.
steve authored
343
03d7448 compare-to-constant uses sig len, not val len.
steve authored
344 /* Look for the very special case that we know the compare
345 results a priori due to different high bits, that are
346 constant pad in the signal. */
ead2481 Fix elaboration of == compared to constants.
steve authored
347 if (val.len() > lsig->vector_width()) {
348 unsigned idx = lsig->vector_width();
03d7448 compare-to-constant uses sig len, not val len.
steve authored
349 verinum::V lpad = verinum::V0;
350
351 while (idx < val.len()) {
352 if (val.get(idx) != lpad) {
353 verinum oval (op_code == 'e'
354 ? verinum::V0
355 : verinum::V1,
356 1);
357 NetEConst*ogate = new NetEConst(oval);
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
358 NetNet*osig = ogate->synthesize(des, scope);
0c9fb76 Get the data type of part select results right.
steve authored
359 osig->data_type(lsig->data_type());
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
360 osig->set_line(*lsig);
361 osig->rise_time(rise);
362 osig->fall_time(fall);
363 osig->decay_time(decay);
03d7448 compare-to-constant uses sig len, not val len.
steve authored
364 delete ogate;
ead2481 Fix elaboration of == compared to constants.
steve authored
365
366 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
367 cerr << lsig->get_fileline() << ": debug: "
ead2481 Fix elaboration of == compared to constants.
steve authored
368 << "Equality replaced with "
369 << oval << " due to high pad mismatch"
370 << endl;
371
03d7448 compare-to-constant uses sig len, not val len.
steve authored
372 return osig;
373 }
374
375 idx +=1;
376 }
377 }
fd371a3 Handle equality compare to constants specially.
steve authored
378
379 unsigned zeros = 0;
380 unsigned ones = 0;
ead2481 Fix elaboration of == compared to constants.
steve authored
381 for (unsigned idx = 0 ; idx < lsig->vector_width() ; idx += 1) {
fd371a3 Handle equality compare to constants specially.
steve authored
382 if (val.get(idx) == verinum::V0)
383 zeros += 1;
384 if (val.get(idx) == verinum::V1)
385 ones += 1;
386 }
387
c34e44d Make sig-eq-constant optimization more effective.
steve authored
388 /* Handle the special case that the gate is a compare that can
389 be replaces with a reduction AND or NOR. */
390
391 if (ones == 0 || zeros == 0) {
392 NetUReduce::TYPE type;
393
394 if (zeros > 0) {
395 type = op_code == 'e'? NetUReduce::NOR : NetUReduce::OR;
396
6694912 @ldoolitt Non-controversial whitespace cleanup
ldoolitt authored
397 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
398 cerr << lsig->get_fileline() << ": debug: "
c34e44d Make sig-eq-constant optimization more effective.
steve authored
399 << "Replace net==" << val << " equality with "
400 << zeros << "-input reduction [N]OR gate." << endl;
401
402 } else {
403 type = op_code == 'e'? NetUReduce::AND : NetUReduce::NAND;
404
6694912 @ldoolitt Non-controversial whitespace cleanup
ldoolitt authored
405 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
406 cerr << lsig->get_fileline() << ": debug: "
c34e44d Make sig-eq-constant optimization more effective.
steve authored
407 << "Replace net==" << val << " equality with "
408 << ones << "-input reduction AND gate." << endl;
409 }
410
411 NetUReduce*red = new NetUReduce(scope, scope->local_symbol(),
412 type, zeros+ones);
413 des->add_node(red);
414 red->set_line(*lsig);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
415 red->rise_time(rise);
416 red->fall_time(fall);
417 red->decay_time(decay);
ead2481 Fix elaboration of == compared to constants.
steve authored
418
419 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
420 NetNet::WIRE, 0, 0);
0c9fb76 Get the data type of part select results right.
steve authored
421 tmp->data_type(lsig->data_type());
ead2481 Fix elaboration of == compared to constants.
steve authored
422 tmp->local_flag(true);
423 tmp->set_line(*lsig);
fd371a3 Handle equality compare to constants specially.
steve authored
424
c34e44d Make sig-eq-constant optimization more effective.
steve authored
425 connect(red->pin(1), lsig->pin(0));
426 connect(red->pin(0), tmp->pin(0));
427 return tmp;
fd371a3 Handle equality compare to constants specially.
steve authored
428 }
429
c34e44d Make sig-eq-constant optimization more effective.
steve authored
430 if (debug_elaborate)
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
431 cerr << lsig->get_fileline() << ": debug: "
c34e44d Make sig-eq-constant optimization more effective.
steve authored
432 << "Give up trying to replace net==" << val
433 << " equality with "
434 << ones << "-input AND and "
435 << zeros << "-input NOR gates." << endl;
436
437 return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
438 }
439
440 /*
3d1ffce Elaborate net widths of constants to as small
steve authored
441 * Elaborate the various binary comparison operators. The comparison
442 * operators return a single bit result, no matter what, so the left
443 * and right values can have their own size. The only restriction is
444 * that they have the same size.
206b37e Fix NetConst being set to zero width, and clean
steve authored
445 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
446 NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
206b37e Fix NetConst being set to zero width, and clean
steve authored
447 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
448 const NetExpr* rise,
449 const NetExpr* fall,
450 const NetExpr* decay) const
206b37e Fix NetConst being set to zero width, and clean
steve authored
451 {
2f8a40b Fix evaluation of compare to constant expression.
steve authored
452 /* Elaborate the operands of the compare first as expressions
453 (so that the eval_tree method can reduce constant
454 expressions, including parameters) then turn those results
455 into synthesized nets. */
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
456 NetExpr*lexp = elab_and_eval(des, scope, left_, -1),
457 *rexp = elab_and_eval(des, scope, right_, -1);
2f8a40b Fix evaluation of compare to constant expression.
steve authored
458
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
459 if (lexp == 0 || rexp == 0) return 0;
206b37e Fix NetConst being set to zero width, and clean
steve authored
460
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
461 bool real_arg = true;
462 if (lexp->expr_type() != IVL_VT_REAL &&
463 rexp->expr_type() != IVL_VT_REAL) {
06e08db Make sure comparison widths match.
steve authored
464 /* Choose the operand width to be the width of the widest
465 self-determined operand. */
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
466 unsigned operand_width = lexp->expr_width();
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
467 if (rexp->expr_width() > operand_width)
468 operand_width = rexp->expr_width();
06e08db Make sure comparison widths match.
steve authored
469
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
470 lexp->set_width(operand_width);
471 lexp = pad_to_width(lexp, operand_width);
472 rexp->set_width(operand_width);
473 rexp = pad_to_width(rexp, operand_width);
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
474
475 real_arg = false;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
476 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
477
fd371a3 Handle equality compare to constants specially.
steve authored
478 NetNet*lsig = 0;
479 NetNet*rsig = 0;
480
481 /* Handle the special case that the right or left
482 sub-expression is a constant value. The compare_eq_constant
483 function will return an elaborated result if it can make
484 use of the situation, or 0 if it cannot. */
485 if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
486
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
487 lsig = lexp->synthesize(des, scope);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
488 if (lsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
489 delete lexp;
490 lexp = 0;
491
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
492 if (real_arg) {
493 verireal vrl(tmp->value().as_double());
494 NetECReal rlval(vrl);
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
495 rsig = rlval.synthesize(des, scope);
eac6333 @caryr Add missing deletes for patch "Add real compar..."
caryr authored
496 delete rexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
497 rexp = 0;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
498 } else {
499 NetNet*osig = compare_eq_constant(des, scope,
500 lsig, tmp, op_,
501 rise, fall, decay);
502 if (osig != 0) {
503 delete rexp;
504 return osig;
505 }
fd371a3 Handle equality compare to constants specially.
steve authored
506 }
507 }
508
509 if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
510
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
511 rsig = rexp->synthesize(des, scope);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
512 if (rsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
513 delete rexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
514 rexp = 0;
fd371a3 Handle equality compare to constants specially.
steve authored
515
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
516 if (real_arg) {
517 verireal vrl(tmp->value().as_double());
518 NetECReal rlval(vrl);
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
519 lsig = rlval.synthesize(des, scope);
eac6333 @caryr Add missing deletes for patch "Add real compar..."
caryr authored
520 delete lexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
521 lexp = 0;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
522 } else {
523 NetNet*osig = compare_eq_constant(des, scope,
524 rsig, tmp, op_,
525 rise, fall, decay);
526 if (osig != 0) {
527 delete lexp;
528 return osig;
529 }
fd371a3 Handle equality compare to constants specially.
steve authored
530 }
531 }
532
533 if (lsig == 0) {
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
534 lsig = lexp->synthesize(des, scope);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
535 if (lsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
536 delete lexp;
537 }
538
539 if (rsig == 0) {
1d884cb @steveicarus Shuffle the argument list for the synthesize method.
authored
540 rsig = rexp->synthesize(des, scope);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
541 if (rsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
542 delete rexp;
543 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
544
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
545 unsigned dwidth = lsig->vector_width();
546 if (rsig->vector_width() > dwidth) dwidth = rsig->vector_width();
3d1ffce Elaborate net widths of constants to as small
steve authored
547
5d1d99a Handle signed magnitude compare all the
steve authored
548 /* Operands of binary compare need to be padded to equal
549 size. Figure the pad bit needed to extend the narrowest
550 vector. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
551 if (!real_arg && lsig->vector_width() < dwidth)
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
552 lsig = pad_to_width(des, lsig, dwidth);
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
553 if (!real_arg && rsig->vector_width() < dwidth)
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
554 rsig = pad_to_width(des, rsig, dwidth);
5d1d99a Handle signed magnitude compare all the
steve authored
555
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
556 /* For now the runtime cannot convert a vec4 to a real value. */
557 if (real_arg && (rsig->data_type() != IVL_VT_REAL ||
558 lsig->data_type() != IVL_VT_REAL)) {
559 cerr << get_fileline() << ": sorry: comparing bit based signals "
560 "and real values is not supported." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
561 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
562 return 0;
563 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
564
badad63 All NetObj objects have lex_string base names.
steve authored
565 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
75ad905 Generalize signals to carry types.
steve authored
566 osig->data_type(IVL_VT_LOGIC);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
567 osig->set_line(*this);
206b37e Fix NetConst being set to zero width, and clean
steve authored
568 osig->local_flag(true);
569
570 NetNode*gate;
571
572 switch (op_) {
513ade9 Support combinatorial comparators.
steve authored
573 case '<':
574 case '>':
575 case 'L':
576 case 'G': {
3d1ffce Elaborate net widths of constants to as small
steve authored
577 NetCompare*cmp = new
a275133 LPM objects store only their base names.
steve authored
578 NetCompare(scope, scope->local_symbol(), dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
579 connect(cmp->pin_DataA(), lsig->pin(0));
580 connect(cmp->pin_DataB(), rsig->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
581
513ade9 Support combinatorial comparators.
steve authored
582 switch (op_) {
583 case '<':
584 connect(cmp->pin_ALB(), osig->pin(0));
585 break;
586 case '>':
587 connect(cmp->pin_AGB(), osig->pin(0));
588 break;
589 case 'L':
590 connect(cmp->pin_ALEB(), osig->pin(0));
591 break;
592 case 'G':
593 connect(cmp->pin_AGEB(), osig->pin(0));
594 break;
595 }
5d1d99a Handle signed magnitude compare all the
steve authored
596 /* If both operands are signed, then do a signed
597 compare. */
598 if (lsig->get_signed() && rsig->get_signed())
599 cmp->set_signed(true);
600
513ade9 Support combinatorial comparators.
steve authored
601 gate = cmp;
602 break;
603 }
604
206b37e Fix NetConst being set to zero width, and clean
steve authored
605 case 'E': // Case equals (===)
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
606 if (real_arg) {
607 cerr << get_fileline() << ": error: Case equality may not "
608 "have real operands." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
609 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
610 return 0;
611 }
1c5b488 Handle case inequality in netlists.
steve authored
612 gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
206b37e Fix NetConst being set to zero width, and clean
steve authored
613 connect(gate->pin(0), osig->pin(0));
e286367 Change case compare from logic to an LPM node.
steve authored
614 connect(gate->pin(1), lsig->pin(0));
615 connect(gate->pin(2), rsig->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
616 break;
617
e286367 Change case compare from logic to an LPM node.
steve authored
618 case 'N': // Case equals (!==)
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
619 if (real_arg) {
620 cerr << get_fileline() << ": error: Case inequality may not "
621 "have real operands." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
622 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
623 return 0;
624 }
1c5b488 Handle case inequality in netlists.
steve authored
625 gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
626 connect(gate->pin(0), osig->pin(0));
627 connect(gate->pin(1), lsig->pin(0));
628 connect(gate->pin(2), rsig->pin(0));
e286367 Change case compare from logic to an LPM node.
steve authored
629 break;
206b37e Fix NetConst being set to zero width, and clean
steve authored
630
631 case 'e': // ==
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
632
633 /* Handle the special case of single bit compare with a
634 single XNOR gate. This is easy and direct. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
635 if (dwidth == 1 && !real_arg){
badad63 All NetObj objects have lex_string base names.
steve authored
636 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
637 3, NetLogic::XNOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
638 connect(gate->pin(0), osig->pin(0));
639 connect(gate->pin(1), lsig->pin(0));
640 connect(gate->pin(2), rsig->pin(0));
641 break;
642 }
643
d548c9a Handle synthesis of concatenation expressions.
steve authored
644 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
645 cerr << get_fileline() << ": debug: Elaborate net == gate."
d548c9a Handle synthesis of concatenation expressions.
steve authored
646 << endl;
647 }
648
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
649 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
650 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
651 dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
652 connect(cmp->pin_DataA(), lsig->pin(0));
653 connect(cmp->pin_DataB(), rsig->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
654 connect(cmp->pin_AEB(), osig->pin(0));
655 gate = cmp;
206b37e Fix NetConst being set to zero width, and clean
steve authored
656 }
657 break;
658
659 case 'n': // !=
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
660
661 /* Handle the special case of single bit compare with a
662 single XOR gate. This is easy and direct. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
663 if (dwidth == 1 && lsig->data_type() != IVL_VT_REAL &&
664 rsig->data_type() != IVL_VT_REAL) {
badad63 All NetObj objects have lex_string base names.
steve authored
665 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
666 3, NetLogic::XOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
667 connect(gate->pin(0), osig->pin(0));
668 connect(gate->pin(1), lsig->pin(0));
669 connect(gate->pin(2), rsig->pin(0));
670 break;
671 }
672
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
673 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
674 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
675 dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
676 connect(cmp->pin_DataA(), lsig->pin(0));
677 connect(cmp->pin_DataB(), rsig->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
678 connect(cmp->pin_ANEB(), osig->pin(0));
679 gate = cmp;
680 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
681 break;
682
683 default:
684 assert(0);
685 }
686
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
687 gate->set_line(*this);
206b37e Fix NetConst being set to zero width, and clean
steve authored
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 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
707 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
708 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
694ff93 Add support for integer division.
steve authored
709
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
710 if (lsig == 0 || rsig == 0) return 0;
8ee00ec Fix net division to cope with small output sizes.
steve authored
711
712 // Check the l-value width. If it is unspecified, then use the
713 // largest operand width as the l-value width. Restrict the
714 // result width to the width of the largest operand, because
715 // there is no value is excess divider.
716
717 unsigned rwidth = lwidth;
718
3772369 @steveicarus Handle non-real operands to real division.
authored
719 // If either operand is IVL_VT_REAL, then cast the other to
720 // IVL_VT_REAL so that the division can become IVL_VT_REAL.
721
722 if (lsig->data_type()==IVL_VT_REAL || rsig->data_type()==IVL_VT_REAL) {
723 if (lsig->data_type() != IVL_VT_REAL)
724 lsig = cast_to_real(des, scope, lsig);
725 if (rsig->data_type() != IVL_VT_REAL)
726 rsig = cast_to_real(des, scope, rsig);
727 }
728
8ee00ec Fix net division to cope with small output sizes.
steve authored
729 if (rwidth == 0) {
257e1f9 Support shifts and divide.
steve authored
730 rwidth = lsig->vector_width();
731 if (rsig->vector_width() > rwidth)
732 rwidth = rsig->vector_width();
8ee00ec Fix net division to cope with small output sizes.
steve authored
733
734 lwidth = rwidth;
735 }
736
257e1f9 Support shifts and divide.
steve authored
737 if ((rwidth > lsig->vector_width()) && (rwidth > rsig->vector_width())) {
738 rwidth = lsig->vector_width();
739 if (rsig->vector_width() > rwidth)
740 rwidth = rsig->vector_width();
8ee00ec Fix net division to cope with small output sizes.
steve authored
741 }
742
75ad905 Generalize signals to carry types.
steve authored
743 /* The arguments of a divide must have the same type. */
744 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
745 cerr << get_fileline() << ": error: Arguments of divide "
75ad905 Generalize signals to carry types.
steve authored
746 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
747 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
748 << lsig->data_type() << ", right argument is "
749 << rsig->data_type() << "." << endl;
750 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
751 return 0;
75ad905 Generalize signals to carry types.
steve authored
752 }
753
8ee00ec Fix net division to cope with small output sizes.
steve authored
754 // Create a device with the calculated dimensions.
a275133 LPM objects store only their base names.
steve authored
755 NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth,
257e1f9 Support shifts and divide.
steve authored
756 lsig->vector_width(),
757 rsig->vector_width());
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
758 div->set_line(*this);
759 div->rise_time(rise);
760 div->fall_time(fall);
761 div->decay_time(decay);
694ff93 Add support for integer division.
steve authored
762 des->add_node(div);
763
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
764 div->set_signed(lsig->get_signed() && rsig->get_signed());
8ee00ec Fix net division to cope with small output sizes.
steve authored
765
766 // Connect the left and right inputs of the divider to the
767 // nets that are the left and right expressions.
768
257e1f9 Support shifts and divide.
steve authored
769 connect(div->pin_DataA(), lsig->pin(0));
770 connect(div->pin_DataB(), rsig->pin(0));
694ff93 Add support for integer division.
steve authored
771
8ee00ec Fix net division to cope with small output sizes.
steve authored
772
773 // Make an output signal that is the width of the l-value.
774 // Due to above calculation of rwidth, we know that the result
611d2c8 Spelling fixes from Larry
steve authored
775 // 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
776 // all the result pins to the osig.
777
badad63 All NetObj objects have lex_string base names.
steve authored
778 NetNet*osig = new NetNet(scope, scope->local_symbol(),
694ff93 Add support for integer division.
steve authored
779 NetNet::IMPLICIT, lwidth);
780 osig->local_flag(true);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
781 osig->set_line(*this);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
782 osig->data_type( lsig->data_type() );
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
783 osig->set_signed(div->get_signed());
694ff93 Add support for integer division.
steve authored
784
257e1f9 Support shifts and divide.
steve authored
785 connect(div->pin_Result(), osig->pin(0));
8ee00ec Fix net division to cope with small output sizes.
steve authored
786
694ff93 Add support for integer division.
steve authored
787
788 return osig;
789 }
790
89d7176 Add support for modulus (Eric Aardoom)
steve authored
791 /*
792 * Elaborate a modulo gate.
793 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
794 NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
89d7176 Add support for modulus (Eric Aardoom)
steve authored
795 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
796 const NetExpr* rise,
797 const NetExpr* fall,
798 const NetExpr* decay) const
89d7176 Add support for modulus (Eric Aardoom)
steve authored
799 {
50a8c17 @caryr Comparison arguments are in a self determined context.
caryr authored
800 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
801 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
802
803 if (lsig == 0 || rsig == 0) return 0;
89d7176 Add support for modulus (Eric Aardoom)
steve authored
804
75ad905 Generalize signals to carry types.
steve authored
805 /* The arguments of a modulus must have the same type. */
806 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
807 cerr << get_fileline() << ": error: Arguments of modulus "
75ad905 Generalize signals to carry types.
steve authored
808 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
809 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
810 << lsig->data_type() << ", right argument is "
811 << rsig->data_type() << "." << endl;
812 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
813 return 0;
75ad905 Generalize signals to carry types.
steve authored
814 }
815
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
816 /* The % operator does not support real arguments in baseline
817 Verilog. But we allow it in our extended form of Verilog. */
3a61b94 @steveicarus Realign generation flags to correspond to IEEE1364 nomenclature.
authored
818 if (gn_icarus_misc_flag==false && lsig->data_type() == IVL_VT_REAL) {
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
819 cerr << get_fileline() << ": error: Modulus operator may not "
820 "have REAL operands." << endl;
4c5481f @caryr Add delays for shifts, concatenation and replication in a CA.
caryr authored
821 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
822 return 0;
4c5481f @caryr Add delays for shifts, concatenation and replication in a CA.
caryr authored
823 }
824
ab1ca54 Update support for LPM_MOD.
steve authored
825 /* rwidth is result width. */
dd79885 Add structural modulus support down to vvp.
steve authored
826 unsigned rwidth = lwidth;
827 if (rwidth == 0) {
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
828 /* Reals are always 1 wide and lsig/rsig types match here. */
829 if (lsig->data_type() == IVL_VT_REAL) {
830 lwidth = 1;
831 rwidth = 1;
832 } else {
833 rwidth = lsig->vector_width();
834 if (rsig->vector_width() > rwidth)
835 rwidth = rsig->vector_width();
ab1ca54 Update support for LPM_MOD.
steve authored
836
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
837 lwidth = rwidth;
838 }
dd79885 Add structural modulus support down to vvp.
steve authored
839 }
ab1ca54 Update support for LPM_MOD.
steve authored
840
a275133 LPM objects store only their base names.
steve authored
841 NetModulo*mod = new NetModulo(scope, scope->local_symbol(), rwidth,
ab1ca54 Update support for LPM_MOD.
steve authored
842 lsig->vector_width(),
843 rsig->vector_width());
7235706 Make sure div, mod and mult nodes have line number info.
steve authored
844 mod->set_line(*this);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
845 mod->rise_time(rise);
846 mod->fall_time(fall);
847 mod->decay_time(decay);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
848 des->add_node(mod);
849
ab1ca54 Update support for LPM_MOD.
steve authored
850 connect(mod->pin_DataA(), lsig->pin(0));
851 connect(mod->pin_DataB(), rsig->pin(0));
89d7176 Add support for modulus (Eric Aardoom)
steve authored
852
badad63 All NetObj objects have lex_string base names.
steve authored
853 NetNet*osig = new NetNet(scope, scope->local_symbol(),
ab1ca54 Update support for LPM_MOD.
steve authored
854 NetNet::IMPLICIT, rwidth);
7235706 Make sure div, mod and mult nodes have line number info.
steve authored
855 osig->set_line(*this);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
856 osig->data_type( lsig->data_type() );
89d7176 Add support for modulus (Eric Aardoom)
steve authored
857 osig->local_flag(true);
858
ab1ca54 Update support for LPM_MOD.
steve authored
859 connect(mod->pin_Result(), osig->pin(0));
89d7176 Add support for modulus (Eric Aardoom)
steve authored
860
861 return osig;
862 }
863
7793a49 Remove string paths from PExpr elaboration.
steve authored
864 NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
ced7cc6 Structural logical or.
steve authored
865 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
866 const NetExpr* rise,
867 const NetExpr* fall,
868 const NetExpr* decay) const
ced7cc6 Structural logical or.
steve authored
869 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
870 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
871 *rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
872
873 if (lsig == 0 || rsig == 0) return 0;
874
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
875 if (rsig->data_type() == IVL_VT_REAL ||
876 lsig->data_type() == IVL_VT_REAL) {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
877 cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
878 << " is currently unsupported for real values." << endl;
879 des->errors += 1;
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
880 return 0;
881 }
ced7cc6 Structural logical or.
steve authored
882
883 NetLogic*gate;
884 switch (op_) {
885 case 'a':
badad63 All NetObj objects have lex_string base names.
steve authored
886 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
887 3, NetLogic::AND, 1);
ced7cc6 Structural logical or.
steve authored
888 break;
889 case 'o':
badad63 All NetObj objects have lex_string base names.
steve authored
890 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
891 3, NetLogic::OR, 1);
ced7cc6 Structural logical or.
steve authored
892 break;
893 default:
894 assert(0);
895 }
896
897 // The first OR gate returns 1 if the left value is true...
8184dfa Handle wide operands to logical AND.
steve authored
898 if (lsig->vector_width() > 1) {
899 NetUReduce*gate_tmp = new NetUReduce(scope, scope->local_symbol(),
900 NetUReduce::OR,
901 lsig->vector_width());
902 connect(gate_tmp->pin(1), lsig->pin(0));
903 connect(gate->pin(1), gate_tmp->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
904
905 /* The reduced logical value is a new nexus, create a
906 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
907 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
908 NetNet::IMPLICIT, 1);
a8b86ea More explicit datatype setup.
steve authored
909 tmp->data_type(IVL_VT_LOGIC);
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
910 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
911 connect(gate->pin(1), tmp->pin(0));
912
8184dfa Handle wide operands to logical AND.
steve authored
913 des->add_node(gate_tmp);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
914
ced7cc6 Structural logical or.
steve authored
915 } else {
916 connect(gate->pin(1), lsig->pin(0));
917 }
918
919 // The second OR gate returns 1 if the right value is true...
8184dfa Handle wide operands to logical AND.
steve authored
920 if (rsig->vector_width() > 1) {
921 NetUReduce*gate_tmp = new NetUReduce(scope, scope->local_symbol(),
922 NetUReduce::OR,
923 rsig->vector_width());
924 connect(gate_tmp->pin(1), rsig->pin(0));
925 connect(gate->pin(2), gate_tmp->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
926
927 /* The reduced logical value is a new nexus, create a
928 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
929 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
930 NetNet::IMPLICIT, 1);
a8b86ea More explicit datatype setup.
steve authored
931 tmp->data_type(IVL_VT_LOGIC);
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
932 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
933 connect(gate->pin(2), tmp->pin(0));
934
8184dfa Handle wide operands to logical AND.
steve authored
935 des->add_node(gate_tmp);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
936
ced7cc6 Structural logical or.
steve authored
937 } else {
938 connect(gate->pin(2), rsig->pin(0));
939 }
940
941 // The output is the AND/OR of the two logic values.
badad63 All NetObj objects have lex_string base names.
steve authored
942 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
ced7cc6 Structural logical or.
steve authored
943 osig->local_flag(true);
07f345d Logical or/and return VT_LOGIC type.
steve authored
944 osig->data_type(IVL_VT_LOGIC);
ced7cc6 Structural logical or.
steve authored
945 connect(gate->pin(0), osig->pin(0));
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
946
947 gate->set_line(*this);
948 gate->rise_time(rise);
949 gate->fall_time(fall);
950 gate->decay_time(decay);
ced7cc6 Structural logical or.
steve authored
951 des->add_node(gate);
952 return osig;
953 }
954
7793a49 Remove string paths from PExpr elaboration.
steve authored
955 NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
aa8908c Multiplication all the way to simulation.
steve authored
956 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
957 const NetExpr* rise,
958 const NetExpr* fall,
959 const NetExpr* decay) const
aa8908c Multiplication all the way to simulation.
steve authored
960 {
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
961 verinum*lnum = left_->eval_const(des, scope);
962 verinum*rnum = right_->eval_const(des, scope);
963
964 /* Detect and handle the special case that both the operands
8f0c02c Spelling fixes.
steve authored
965 of the multiply are constant expressions. Evaluate the
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
966 value and make this a simple constant. */
967 if (lnum && rnum) {
968 verinum prod = *lnum * *rnum;
969 if (lwidth == 0)
970 lwidth = prod.len();
971
972 verinum res (verinum::V0, lwidth);
973 for (unsigned idx = 0
974 ; idx < prod.len() && idx < lwidth
975 ; idx += 1) {
976 res.set(idx, prod.get(idx));
977 }
978
badad63 All NetObj objects have lex_string base names.
steve authored
979 NetConst*odev = new NetConst(scope, scope->local_symbol(), res);
22efa9f Fix elaboration of multiply of two constants.
steve authored
980 des->add_node(odev);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
981 odev->rise_time(rise);
982 odev->fall_time(fall);
983 odev->decay_time(decay);
22efa9f Fix elaboration of multiply of two constants.
steve authored
984 odev->set_line(*this);
985
badad63 All NetObj objects have lex_string base names.
steve authored
986 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
987 NetNet::IMPLICIT, lwidth);
22efa9f Fix elaboration of multiply of two constants.
steve authored
988 osig->set_line(*this);
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
989 osig->local_flag(true);
22efa9f Fix elaboration of multiply of two constants.
steve authored
990 osig->data_type(IVL_VT_LOGIC);
991
992 connect(odev->pin(0), osig->pin(0));
993
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
994 return osig;
995 }
996
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
997 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
998 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
999
1000 if (lsig == 0 || rsig == 0) return 0;
aa8908c Multiplication all the way to simulation.
steve authored
1001
ea1f448 @caryr Real multiply in a cont. assign. is always 1 bit wide.
caryr authored
1002 /* The arguments of a multiply must have the same type. */
75ad905 Generalize signals to carry types.
steve authored
1003 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1004 cerr << get_fileline() << ": error: Arguments of multiply "
75ad905 Generalize signals to carry types.
steve authored
1005 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1006 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
1007 << lsig->data_type() << ", right argument is "
1008 << rsig->data_type() << "." << endl;
1009 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1010 return 0;
75ad905 Generalize signals to carry types.
steve authored
1011 }
1012
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1013 // The mult is signed if both its operands are signed.
1014 bool arith_is_signed = lsig->get_signed() && rsig->get_signed();
75ad905 Generalize signals to carry types.
steve authored
1015
4124273 Handle some special cases of unary 2's complement,
steve authored
1016 unsigned rwidth = lwidth;
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
1017 if (rwidth == 0) {
ea1f448 @caryr Real multiply in a cont. assign. is always 1 bit wide.
caryr authored
1018 /* Reals are always 1 wide and lsig/rsig types match here. */
1019 if (lsig->data_type() == IVL_VT_REAL) {
1020 rwidth = 1;
1021 lwidth = 1;
1022 } else {
1023 rwidth = lsig->vector_width() + rsig->vector_width();
1024 lwidth = rwidth;
1025 }
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
1026 }
1027
739a183 Do sign extension of structuran nets.
steve authored
1028 if (arith_is_signed) {
1029 lsig = pad_to_width_signed(des, lsig, rwidth);
1030 rsig = pad_to_width_signed(des, rsig, rwidth);
1031 }
1032
a275133 LPM objects store only their base names.
steve authored
1033 NetMult*mult = new NetMult(scope, scope->local_symbol(), rwidth,
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1034 lsig->vector_width(),
1035 rsig->vector_width());
1036 mult->set_line(*this);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
1037 mult->rise_time(rise);
1038 mult->fall_time(fall);
1039 mult->decay_time(decay);
aa8908c Multiplication all the way to simulation.
steve authored
1040 des->add_node(mult);
1041
739a183 Do sign extension of structuran nets.
steve authored
1042 mult->set_signed( arith_is_signed );
d18934d Sign extend NetMult inputs if result is signed.
steve authored
1043
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1044 connect(mult->pin_DataA(), lsig->pin(0));
1045 connect(mult->pin_DataB(), rsig->pin(0));
aa8908c Multiplication all the way to simulation.
steve authored
1046
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1047 /* Make a signal to carry the output from the multiply. */
badad63 All NetObj objects have lex_string base names.
steve authored
1048 NetNet*osig = new NetNet(scope, scope->local_symbol(),
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1049 NetNet::IMPLICIT, rwidth);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1050 osig->data_type( lsig->data_type() );
aa8908c Multiplication all the way to simulation.
steve authored
1051 osig->local_flag(true);
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1052 connect(mult->pin_Result(), osig->pin(0));
aa8908c Multiplication all the way to simulation.
steve authored
1053
1054 return osig;
1055 }
1056
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1057 NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
1058 unsigned lwidth,
1059 const NetExpr* rise,
1060 const NetExpr* fall,
1061 const NetExpr* decay) const
1062 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1063 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
1064 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
1065
1066 if (lsig == 0 || rsig == 0) return 0;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1067
1068 /* The arguments of a power must have the same type. */
1069 if (lsig->data_type() != rsig->data_type()) {
1070 cerr << get_fileline() << ": error: Arguments of power "
1071 << "have different data types." << endl;
1072 cerr << get_fileline() << ": : Left argument is "
1073 << lsig->data_type() << ", right argument is "
1074 << rsig->data_type() << "." << endl;
1075 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1076 return 0;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1077 }
1078
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1079 /* The power is signed if either of its operands are signed. */
85229a6 @caryr Add unsigned bit based power to continuous assignments.
caryr authored
1080 bool arith_is_signed = lsig->get_signed() || rsig->get_signed();
1081
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1082 unsigned rwidth = lwidth;
1083 if (rwidth == 0) {
1084 /* Reals are always 1 wide and lsig/rsig types match here. */
1085 if (lsig->data_type() == IVL_VT_REAL) {
1086 rwidth = 1;
1087 lwidth = 1;
1088 } else {
331faa2 @caryr Add signed bit based power to continuous assignments.
caryr authored
1089 /* This is incorrect! a * (2^b - 1) is close. */
1090 rwidth = lsig->vector_width() + rsig->vector_width();
1091 lwidth = rwidth;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1092 }
1093 }
1094
1095 if (arith_is_signed) {
1096 lsig = pad_to_width_signed(des, lsig, rwidth);
1097 rsig = pad_to_width_signed(des, rsig, rwidth);
1098 }
1099
1100 NetPow*powr = new NetPow(scope, scope->local_symbol(), rwidth,
1101 lsig->vector_width(),
1102 rsig->vector_width());
1103 powr->set_line(*this);
1104 powr->rise_time(rise);
1105 powr->fall_time(fall);
1106 powr->decay_time(decay);
1107 des->add_node(powr);
1108
1109 powr->set_signed( arith_is_signed );
1110
1111 connect(powr->pin_DataA(), lsig->pin(0));
1112 connect(powr->pin_DataB(), rsig->pin(0));
1113
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1114 /* Make a signal to carry the output from the power. */
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1115 NetNet*osig = new NetNet(scope, scope->local_symbol(),
1116 NetNet::IMPLICIT, rwidth);
1117 osig->data_type( lsig->data_type() );
1118 osig->local_flag(true);
1119 connect(powr->pin_Result(), osig->pin(0));
1120
1121 return osig;
1122 }
1123
7793a49 Remove string paths from PExpr elaboration.
steve authored
1124 NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1125 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
1126 const NetExpr* rise,
1127 const NetExpr* fall,
1128 const NetExpr* decay) const
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1129 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
1130 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1131
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1132 if (lsig == 0) return 0;
1133
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1134 /* Cannot shift a real value. */
1135 if (lsig->data_type() == IVL_VT_REAL) {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1136 cerr << get_fileline() << ": error: shift operators ("
1137 << human_readable_op(op_)
1138 << ") cannot shift a real value." << endl;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1139 des->errors += 1;
1140 return 0;
1141 }
1142
257e1f9 Support shifts and divide.
steve authored
1143 if (lsig->vector_width() > lwidth)
1144 lwidth = lsig->vector_width();
9e5ff89 Add structural reduction NAND,
steve authored
1145
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1146 bool right_flag = op_ == 'r' || op_ == 'R';
1147 bool signed_flag = op_ == 'R';
1148
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1149 /* Handle the special case of a constant shift amount. There
1150 is no reason in this case to create a gate at all, just
1151 connect the lsig to the osig with the bit positions
257e1f9 Support shifts and divide.
steve authored
1152 shifted. Use a NetPartSelect to select the parts of the
1153 left expression that survive the shift, and a NetConcat to
1154 concatenate a constant for padding. */
bf72f39 eval_const uses scope instead of a string path.
steve authored
1155 if (verinum*rval = right_->eval_const(des, scope)) {
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1156 assert(rval->is_defined());
1157 unsigned dist = rval->as_ulong();
1158
257e1f9 Support shifts and divide.
steve authored
1159 /* Very special case: constant 0 shift. Simply return
1160 the left signal again. */
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1161 if (dist == 0) return lsig;
1162
257e1f9 Support shifts and divide.
steve authored
1163 /* The construction that I'm making will ultimately
1164 connect its output to the osig here. This will be the
1165 result that I return from this function. */
badad63 All NetObj objects have lex_string base names.
steve authored
1166 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4124273 Handle some special cases of unary 2's complement,
steve authored
1167 NetNet::WIRE, lwidth);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1168 osig->data_type( lsig->data_type() );
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1169 osig->local_flag(true);
1170
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1171
257e1f9 Support shifts and divide.
steve authored
1172 /* Make the constant zero's that I'm going to pad to the
1173 top or bottom of the left expression. Attach a signal
1174 to its output so that I don't have to worry about it
d9ac146 @ldoolitt Spelling fixes
ldoolitt authored
1175 later. If the left expression is less than the
257e1f9 Support shifts and divide.
steve authored
1176 desired width (and we are doing right shifts) then we
1177 can combine the expression padding with the distance
1178 padding to reduce nodes. */
1179 unsigned pad_width = dist;
1180 unsigned part_width = lwidth - dist;
1181 if (op_ == 'r' || op_ == 'R') {
1182 if (lsig->vector_width() < lwidth) {
1183 pad_width += lwidth - lsig->vector_width();
1184 part_width -= lwidth - lsig->vector_width();
1185 }
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1186 } else {
257e1f9 Support shifts and divide.
steve authored
1187
1188 /* The left net must be the same width as the
1189 result. The part select that I'm about to make relies
1190 on that. */
1191 lsig = pad_to_width(des, lsig, lwidth);
1192
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1193 }
1194
257e1f9 Support shifts and divide.
steve authored
1195 NetNet*zero = new NetNet(scope, scope->local_symbol(),
1196 NetNet::WIRE, pad_width);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1197 zero->data_type( lsig->data_type() );
257e1f9 Support shifts and divide.
steve authored
1198 zero->local_flag(true);
1199 zero->set_line(*this);
1200
31afec5 @ldoolitt Fix for pr1879226, large constant shift values
ldoolitt authored
1201 /* Padding bits are zero in most cases, but copies of
1202 * the sign bit in the case of a signed right shift */
257e1f9 Support shifts and divide.
steve authored
1203 if (op_ == 'R') {
1204 NetPartSelect*sign_bit
1205 = new NetPartSelect(lsig, lsig->vector_width()-1,
1206 1, NetPartSelect::VP);
1207 des->add_node(sign_bit);
1208 NetReplicate*sign_pad
1209 = new NetReplicate(scope, scope->local_symbol(),
1210 pad_width, pad_width);
1211 des->add_node(sign_pad);
1212 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
1213 NetNet::WIRE, 1);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1214 tmp->data_type( lsig->data_type() );
326329d Set some missing local flags.
steve authored
1215 tmp->local_flag(true);
1216 tmp->set_line(*this);
257e1f9 Support shifts and divide.
steve authored
1217 connect(sign_bit->pin(0), tmp->pin(0));
1218 connect(sign_bit->pin(0), sign_pad->pin(1));
1219
1220 connect(zero->pin(0), sign_pad->pin(0));
1221
1222 } else {
1223 NetConst*zero_c = new NetConst(scope, scope->local_symbol(),
1224 verinum(verinum::V0, pad_width));
1225 des->add_node(zero_c);
1226 connect(zero->pin(0), zero_c->pin(0));
1227 }
1228
31afec5 @ldoolitt Fix for pr1879226, large constant shift values
ldoolitt authored
1229 /* If all data bits get shifted away, connect the zero or
6694912 @ldoolitt Non-controversial whitespace cleanup
ldoolitt authored
1230 * padding bits directly to output, and stop before building the
1231 * concatenation. */
31afec5 @ldoolitt Fix for pr1879226, large constant shift values
ldoolitt authored
1232 if (dist >= lwidth) {
1233 connect(osig->pin(0), zero->pin(0));
1234 return osig;
1235 }
1236
257e1f9 Support shifts and divide.
steve authored
1237 /* Make a concatenation operator that will join the
1238 part-selected right expression at the pad values. */
1239 NetConcat*cc = new NetConcat(scope, scope->local_symbol(),
1240 lwidth, 2);
1241 cc->set_line(*this);
1242 des->add_node(cc);
1243 connect(cc->pin(0), osig->pin(0));
1244
1245 /* Make the part select of the left expression and
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
1246 connect it to the LSB or MSB of the concatenation,
257e1f9 Support shifts and divide.
steve authored
1247 depending on the direction of the shift. */
1248 NetPartSelect*part;
1249
1250 switch (op_) {
1251 case 'l': // Left shift === {lsig, zero}
1252 part = new NetPartSelect(lsig, 0, part_width,
1253 NetPartSelect::VP);
1254 connect(cc->pin(1), zero->pin(0));
1255 connect(cc->pin(2), part->pin(0));
1256 break;
1257 case 'R':
1258 case 'r': // right-shift === {zero, lsig}
1259 part = new NetPartSelect(lsig, dist, part_width,
1260 NetPartSelect::VP);
1261 connect(cc->pin(1), part->pin(0));
1262 connect(cc->pin(2), zero->pin(0));
1263 break;
1264 default:
1265 assert(0);
1266 }
1267
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
1268 part->set_line(*this);
1269 part->rise_time(rise);
1270 part->fall_time(fall);
1271 part->decay_time(decay);
257e1f9 Support shifts and divide.
steve authored
1272 des->add_node(part);
1273
4b829bf Get argument widths right for shift results.
steve authored
1274 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1275 cerr << get_fileline() << ": debug: Elaborate shift "
4b829bf Get argument widths right for shift results.
steve authored
1276 << "(" << op_ << ") as concatenation of "
1277 << pad_width << " zeros with " << part_width
1278 << " bits of expression." << endl;
1279 }
1280
257e1f9 Support shifts and divide.
steve authored
1281 /* Attach a signal to the part select output (NetConcat
1282 input) */
1283 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
1284 NetNet::WIRE, part_width);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1285 tmp->data_type( lsig->data_type() );
257e1f9 Support shifts and divide.
steve authored
1286 tmp->local_flag(true);
1287 tmp->set_line(*this);
1288 connect(part->pin(0), tmp->pin(0));
1289
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1290 return osig;
1291 }
1292
9e5ff89 Add structural reduction NAND,
steve authored
1293 // Calculate the number of useful bits for the shift amount,
1294 // and elaborate the right_ expression as the shift amount.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1295 unsigned dwid = 0;
61195c5 Harmless fixup of warnings.
steve authored
1296 while ((1U << dwid) < lwidth)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1297 dwid += 1;
1298
7793a49 Remove string paths from PExpr elaboration.
steve authored
1299 NetNet*rsig = right_->elaborate_net(des, scope, dwid, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1300
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1301 if (rsig == 0) return 0;
1302
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1303 /* You cannot shift a value by a real amount. */
1304 if (rsig->data_type() == IVL_VT_REAL) {
1305 cerr << get_fileline() << ": error: shift operators "
1306 "cannot shift by a real value." << endl;
1307 des->errors += 1;
1308 return 0;
1309 }
1310
9e5ff89 Add structural reduction NAND,
steve authored
1311 // Make the shift device itself, and the output
1312 // NetNet. Connect the Result output pins to the osig signal
a275133 LPM objects store only their base names.
steve authored
1313 NetCLShift*gate = new NetCLShift(scope, scope->local_symbol(),
257e1f9 Support shifts and divide.
steve authored
1314