Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 3679 lines (3085 sloc) 112.617 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),
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);
358 NetNet*osig = ogate->synthesize(des);
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
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
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 {
d548c9a Handle synthesis of concatenation expressions.
steve authored
452
2f8a40b Fix evaluation of compare to constant expression.
steve authored
453 /* Elaborate the operands of the compare first as expressions
454 (so that the eval_tree method can reduce constant
455 expressions, including parameters) then turn those results
456 into synthesized nets. */
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
457 NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth),
458 *rexp = elab_and_eval(des, scope, right_, lwidth);
2f8a40b Fix evaluation of compare to constant expression.
steve authored
459
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
460 if (lexp == 0 || rexp == 0) return 0;
206b37e Fix NetConst being set to zero width, and clean
steve authored
461
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
462 unsigned operand_width;
463 bool real_arg = false;
464 if (lexp->expr_type() == IVL_VT_REAL ||
465 rexp->expr_type() == IVL_VT_REAL) {
466 operand_width = 1;
467 real_arg = true;
468 } else {
06e08db Make sure comparison widths match.
steve authored
469 /* Choose the operand width to be the width of the widest
470 self-determined operand. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
471 operand_width = lexp->expr_width();
472 if (rexp->expr_width() > operand_width)
473 operand_width = rexp->expr_width();
06e08db Make sure comparison widths match.
steve authored
474
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
475 lexp->set_width(operand_width);
476 lexp = pad_to_width(lexp, operand_width);
477 rexp->set_width(operand_width);
478 rexp = pad_to_width(rexp, operand_width);
479 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
480
fd371a3 Handle equality compare to constants specially.
steve authored
481 NetNet*lsig = 0;
482 NetNet*rsig = 0;
483
484 /* Handle the special case that the right or left
485 sub-expression is a constant value. The compare_eq_constant
486 function will return an elaborated result if it can make
487 use of the situation, or 0 if it cannot. */
488 if (NetEConst*tmp = dynamic_cast<NetEConst*>(rexp)) {
489
490 lsig = lexp->synthesize(des);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
491 if (lsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
492 delete lexp;
493 lexp = 0;
494
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
495 if (real_arg) {
496 verireal vrl(tmp->value().as_double());
497 NetECReal rlval(vrl);
498 rsig = rlval.synthesize(des);
eac6333 @caryr Add missing deletes for patch "Add real compar..."
caryr authored
499 delete rexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
500 rexp = 0;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
501 } else {
502 NetNet*osig = compare_eq_constant(des, scope,
503 lsig, tmp, op_,
504 rise, fall, decay);
505 if (osig != 0) {
506 delete rexp;
507 return osig;
508 }
fd371a3 Handle equality compare to constants specially.
steve authored
509 }
510 }
511
512 if (NetEConst*tmp = dynamic_cast<NetEConst*>(lexp)) {
513
514 rsig = rexp->synthesize(des);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
515 if (rsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
516 delete rexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
517 rexp = 0;
fd371a3 Handle equality compare to constants specially.
steve authored
518
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
519 if (real_arg) {
520 verireal vrl(tmp->value().as_double());
521 NetECReal rlval(vrl);
522 lsig = rlval.synthesize(des);
eac6333 @caryr Add missing deletes for patch "Add real compar..."
caryr authored
523 delete lexp;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
524 lexp = 0;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
525 } else {
526 NetNet*osig = compare_eq_constant(des, scope,
527 rsig, tmp, op_,
528 rise, fall, decay);
529 if (osig != 0) {
530 delete lexp;
531 return osig;
532 }
fd371a3 Handle equality compare to constants specially.
steve authored
533 }
534 }
535
536 if (lsig == 0) {
537 lsig = lexp->synthesize(des);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
538 if (lsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
539 delete lexp;
540 }
541
542 if (rsig == 0) {
543 rsig = rexp->synthesize(des);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
544 if (rsig == 0) return 0;
fd371a3 Handle equality compare to constants specially.
steve authored
545 delete rexp;
546 }
2f8a40b Fix evaluation of compare to constant expression.
steve authored
547
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
548 unsigned dwidth = lsig->vector_width();
549 if (rsig->vector_width() > dwidth) dwidth = rsig->vector_width();
3d1ffce Elaborate net widths of constants to as small
steve authored
550
5d1d99a Handle signed magnitude compare all the
steve authored
551 /* Operands of binary compare need to be padded to equal
552 size. Figure the pad bit needed to extend the narrowest
553 vector. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
554 if (!real_arg && lsig->vector_width() < dwidth)
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
555 lsig = pad_to_width(des, lsig, dwidth);
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
556 if (!real_arg && rsig->vector_width() < dwidth)
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
557 rsig = pad_to_width(des, rsig, dwidth);
5d1d99a Handle signed magnitude compare all the
steve authored
558
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
559 /* For now the runtime cannot convert a vec4 to a real value. */
560 if (real_arg && (rsig->data_type() != IVL_VT_REAL ||
561 lsig->data_type() != IVL_VT_REAL)) {
562 cerr << get_fileline() << ": sorry: comparing bit based signals "
563 "and real values is not supported." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
564 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
565 return 0;
566 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
567
badad63 All NetObj objects have lex_string base names.
steve authored
568 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
75ad905 Generalize signals to carry types.
steve authored
569 osig->data_type(IVL_VT_LOGIC);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
570 osig->set_line(*this);
206b37e Fix NetConst being set to zero width, and clean
steve authored
571 osig->local_flag(true);
572
573 NetNode*gate;
574
575 switch (op_) {
513ade9 Support combinatorial comparators.
steve authored
576 case '<':
577 case '>':
578 case 'L':
579 case 'G': {
3d1ffce Elaborate net widths of constants to as small
steve authored
580 NetCompare*cmp = new
a275133 LPM objects store only their base names.
steve authored
581 NetCompare(scope, scope->local_symbol(), dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
582 connect(cmp->pin_DataA(), lsig->pin(0));
583 connect(cmp->pin_DataB(), rsig->pin(0));
3d1ffce Elaborate net widths of constants to as small
steve authored
584
513ade9 Support combinatorial comparators.
steve authored
585 switch (op_) {
586 case '<':
587 connect(cmp->pin_ALB(), osig->pin(0));
588 break;
589 case '>':
590 connect(cmp->pin_AGB(), osig->pin(0));
591 break;
592 case 'L':
593 connect(cmp->pin_ALEB(), osig->pin(0));
594 break;
595 case 'G':
596 connect(cmp->pin_AGEB(), osig->pin(0));
597 break;
598 }
5d1d99a Handle signed magnitude compare all the
steve authored
599 /* If both operands are signed, then do a signed
600 compare. */
601 if (lsig->get_signed() && rsig->get_signed())
602 cmp->set_signed(true);
603
513ade9 Support combinatorial comparators.
steve authored
604 gate = cmp;
605 break;
606 }
607
206b37e Fix NetConst being set to zero width, and clean
steve authored
608 case 'E': // Case equals (===)
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
609 if (real_arg) {
610 cerr << get_fileline() << ": error: Case equality may not "
611 "have real operands." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
612 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
613 return 0;
614 }
1c5b488 Handle case inequality in netlists.
steve authored
615 gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, true);
206b37e Fix NetConst being set to zero width, and clean
steve authored
616 connect(gate->pin(0), osig->pin(0));
e286367 Change case compare from logic to an LPM node.
steve authored
617 connect(gate->pin(1), lsig->pin(0));
618 connect(gate->pin(2), rsig->pin(0));
206b37e Fix NetConst being set to zero width, and clean
steve authored
619 break;
620
e286367 Change case compare from logic to an LPM node.
steve authored
621 case 'N': // Case equals (!==)
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
622 if (real_arg) {
623 cerr << get_fileline() << ": error: Case inequality may not "
624 "have real operands." << endl;
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
625 des->errors += 1;
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
626 return 0;
627 }
1c5b488 Handle case inequality in netlists.
steve authored
628 gate = new NetCaseCmp(scope, scope->local_symbol(), dwidth, false);
629 connect(gate->pin(0), osig->pin(0));
630 connect(gate->pin(1), lsig->pin(0));
631 connect(gate->pin(2), rsig->pin(0));
e286367 Change case compare from logic to an LPM node.
steve authored
632 break;
206b37e Fix NetConst being set to zero width, and clean
steve authored
633
634 case 'e': // ==
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
635
636 /* Handle the special case of single bit compare with a
637 single XNOR gate. This is easy and direct. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
638 if (dwidth == 1 && !real_arg){
badad63 All NetObj objects have lex_string base names.
steve authored
639 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
640 3, NetLogic::XNOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
641 connect(gate->pin(0), osig->pin(0));
642 connect(gate->pin(1), lsig->pin(0));
643 connect(gate->pin(2), rsig->pin(0));
644 break;
645 }
646
d548c9a Handle synthesis of concatenation expressions.
steve authored
647 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
648 cerr << get_fileline() << ": debug: Elaborate net == gate."
d548c9a Handle synthesis of concatenation expressions.
steve authored
649 << endl;
650 }
651
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
652 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
653 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
654 dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
655 connect(cmp->pin_DataA(), lsig->pin(0));
656 connect(cmp->pin_DataB(), rsig->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
657 connect(cmp->pin_AEB(), osig->pin(0));
658 gate = cmp;
206b37e Fix NetConst being set to zero width, and clean
steve authored
659 }
660 break;
661
662 case 'n': // !=
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
663
664 /* Handle the special case of single bit compare with a
665 single XOR gate. This is easy and direct. */
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
666 if (dwidth == 1 && lsig->data_type() != IVL_VT_REAL &&
667 rsig->data_type() != IVL_VT_REAL) {
badad63 All NetObj objects have lex_string base names.
steve authored
668 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
669 3, NetLogic::XOR, 1);
9b59001 Eleminate reduction gate for 1-bit compares.
steve authored
670 connect(gate->pin(0), osig->pin(0));
671 connect(gate->pin(1), lsig->pin(0));
672 connect(gate->pin(2), rsig->pin(0));
673 break;
674 }
675
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
676 /* Oh well, do the general case with a NetCompare. */
a275133 LPM objects store only their base names.
steve authored
677 { NetCompare*cmp = new NetCompare(scope, scope->local_symbol(),
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
678 dwidth);
bf6a5d0 Implement LPM_COMPARE nodes as two-input vector functors.
steve authored
679 connect(cmp->pin_DataA(), lsig->pin(0));
680 connect(cmp->pin_DataB(), rsig->pin(0));
3c8d598 Elaborate == to NetCompare instead of XNOR and AND
steve authored
681 connect(cmp->pin_ANEB(), osig->pin(0));
682 gate = cmp;
683 }
206b37e Fix NetConst being set to zero width, and clean
steve authored
684 break;
685
686 default:
687 assert(0);
688 }
689
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
690 gate->set_line(*this);
206b37e Fix NetConst being set to zero width, and clean
steve authored
691 gate->rise_time(rise);
692 gate->fall_time(fall);
693 gate->decay_time(decay);
694 des->add_node(gate);
695
696 return osig;
697 }
698
694ff93 Add support for integer division.
steve authored
699 /*
8f0c02c Spelling fixes.
steve authored
700 * Elaborate a divider gate. This function create a NetDivide gate
8ee00ec Fix net division to cope with small output sizes.
steve authored
701 * which has exactly the right sized DataA, DataB and Result ports. If
702 * the l-value is wider then the result, then pad.
694ff93 Add support for integer division.
steve authored
703 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
704 NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
694ff93 Add support for integer division.
steve authored
705 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
706 const NetExpr* rise,
707 const NetExpr* fall,
708 const NetExpr* decay) const
694ff93 Add support for integer division.
steve authored
709 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
710 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
711 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
694ff93 Add support for integer division.
steve authored
712
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
713 if (lsig == 0 || rsig == 0) return 0;
8ee00ec Fix net division to cope with small output sizes.
steve authored
714
715 // Check the l-value width. If it is unspecified, then use the
716 // largest operand width as the l-value width. Restrict the
717 // result width to the width of the largest operand, because
718 // there is no value is excess divider.
719
720 unsigned rwidth = lwidth;
721
722 if (rwidth == 0) {
257e1f9 Support shifts and divide.
steve authored
723 rwidth = lsig->vector_width();
724 if (rsig->vector_width() > rwidth)
725 rwidth = rsig->vector_width();
8ee00ec Fix net division to cope with small output sizes.
steve authored
726
727 lwidth = rwidth;
728 }
729
257e1f9 Support shifts and divide.
steve authored
730 if ((rwidth > lsig->vector_width()) && (rwidth > rsig->vector_width())) {
731 rwidth = lsig->vector_width();
732 if (rsig->vector_width() > rwidth)
733 rwidth = rsig->vector_width();
8ee00ec Fix net division to cope with small output sizes.
steve authored
734 }
735
75ad905 Generalize signals to carry types.
steve authored
736 /* The arguments of a divide must have the same type. */
737 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
738 cerr << get_fileline() << ": error: Arguments of divide "
75ad905 Generalize signals to carry types.
steve authored
739 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
740 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
741 << lsig->data_type() << ", right argument is "
742 << rsig->data_type() << "." << endl;
743 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
744 return 0;
75ad905 Generalize signals to carry types.
steve authored
745 }
746
8ee00ec Fix net division to cope with small output sizes.
steve authored
747 // Create a device with the calculated dimensions.
a275133 LPM objects store only their base names.
steve authored
748 NetDivide*div = new NetDivide(scope, scope->local_symbol(), rwidth,
257e1f9 Support shifts and divide.
steve authored
749 lsig->vector_width(),
750 rsig->vector_width());
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
751 div->set_line(*this);
752 div->rise_time(rise);
753 div->fall_time(fall);
754 div->decay_time(decay);
694ff93 Add support for integer division.
steve authored
755 des->add_node(div);
756
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
757 div->set_signed(lsig->get_signed() && rsig->get_signed());
8ee00ec Fix net division to cope with small output sizes.
steve authored
758
759 // Connect the left and right inputs of the divider to the
760 // nets that are the left and right expressions.
761
257e1f9 Support shifts and divide.
steve authored
762 connect(div->pin_DataA(), lsig->pin(0));
763 connect(div->pin_DataB(), rsig->pin(0));
694ff93 Add support for integer division.
steve authored
764
8ee00ec Fix net division to cope with small output sizes.
steve authored
765
766 // Make an output signal that is the width of the l-value.
767 // Due to above calculation of rwidth, we know that the result
611d2c8 Spelling fixes from Larry
steve authored
768 // 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
769 // all the result pins to the osig.
770
badad63 All NetObj objects have lex_string base names.
steve authored
771 NetNet*osig = new NetNet(scope, scope->local_symbol(),
694ff93 Add support for integer division.
steve authored
772 NetNet::IMPLICIT, lwidth);
773 osig->local_flag(true);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
774 osig->set_line(*this);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
775 osig->data_type( lsig->data_type() );
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
776 osig->set_signed(div->get_signed());
694ff93 Add support for integer division.
steve authored
777
257e1f9 Support shifts and divide.
steve authored
778 connect(div->pin_Result(), osig->pin(0));
8ee00ec Fix net division to cope with small output sizes.
steve authored
779
694ff93 Add support for integer division.
steve authored
780
781 return osig;
782 }
783
89d7176 Add support for modulus (Eric Aardoom)
steve authored
784 /*
785 * Elaborate a modulo gate.
786 */
7793a49 Remove string paths from PExpr elaboration.
steve authored
787 NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
89d7176 Add support for modulus (Eric Aardoom)
steve authored
788 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
789 const NetExpr* rise,
790 const NetExpr* fall,
791 const NetExpr* decay) const
89d7176 Add support for modulus (Eric Aardoom)
steve authored
792 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
793 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
794 *rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
795
796 if (lsig == 0 || rsig == 0) return 0;
89d7176 Add support for modulus (Eric Aardoom)
steve authored
797
75ad905 Generalize signals to carry types.
steve authored
798 /* The arguments of a modulus must have the same type. */
799 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
800 cerr << get_fileline() << ": error: Arguments of modulus "
75ad905 Generalize signals to carry types.
steve authored
801 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
802 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
803 << lsig->data_type() << ", right argument is "
804 << rsig->data_type() << "." << endl;
805 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
806 return 0;
75ad905 Generalize signals to carry types.
steve authored
807 }
808
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
809 /* The % operator does not support real arguments in baseline
810 Verilog. But we allow it in our extended form of Verilog. */
3a61b94 @steveicarus Realign generation flags to correspond to IEEE1364 nomenclature.
authored
811 if (gn_icarus_misc_flag==false && lsig->data_type() == IVL_VT_REAL) {
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
812 cerr << get_fileline() << ": error: Modulus operator may not "
813 "have REAL operands." << endl;
4c5481f @caryr Add delays for shifts, concatenation and replication in a CA.
caryr authored
814 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
815 return 0;
4c5481f @caryr Add delays for shifts, concatenation and replication in a CA.
caryr authored
816 }
817
ab1ca54 Update support for LPM_MOD.
steve authored
818 /* rwidth is result width. */
dd79885 Add structural modulus support down to vvp.
steve authored
819 unsigned rwidth = lwidth;
820 if (rwidth == 0) {
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
821 /* Reals are always 1 wide and lsig/rsig types match here. */
822 if (lsig->data_type() == IVL_VT_REAL) {
823 lwidth = 1;
824 rwidth = 1;
825 } else {
826 rwidth = lsig->vector_width();
827 if (rsig->vector_width() > rwidth)
828 rwidth = rsig->vector_width();
ab1ca54 Update support for LPM_MOD.
steve authored
829
f049426 @caryr Add support for real % in a continuous assignment.
caryr authored
830 lwidth = rwidth;
831 }
dd79885 Add structural modulus support down to vvp.
steve authored
832 }
ab1ca54 Update support for LPM_MOD.
steve authored
833
a275133 LPM objects store only their base names.
steve authored
834 NetModulo*mod = new NetModulo(scope, scope->local_symbol(), rwidth,
ab1ca54 Update support for LPM_MOD.
steve authored
835 lsig->vector_width(),
836 rsig->vector_width());
7235706 Make sure div, mod and mult nodes have line number info.
steve authored
837 mod->set_line(*this);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
838 mod->rise_time(rise);
839 mod->fall_time(fall);
840 mod->decay_time(decay);
89d7176 Add support for modulus (Eric Aardoom)
steve authored
841 des->add_node(mod);
842
ab1ca54 Update support for LPM_MOD.
steve authored
843 connect(mod->pin_DataA(), lsig->pin(0));
844 connect(mod->pin_DataB(), rsig->pin(0));
89d7176 Add support for modulus (Eric Aardoom)
steve authored
845
badad63 All NetObj objects have lex_string base names.
steve authored
846 NetNet*osig = new NetNet(scope, scope->local_symbol(),
ab1ca54 Update support for LPM_MOD.
steve authored
847 NetNet::IMPLICIT, rwidth);
7235706 Make sure div, mod and mult nodes have line number info.
steve authored
848 osig->set_line(*this);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
849 osig->data_type( lsig->data_type() );
89d7176 Add support for modulus (Eric Aardoom)
steve authored
850 osig->local_flag(true);
851
ab1ca54 Update support for LPM_MOD.
steve authored
852 connect(mod->pin_Result(), osig->pin(0));
89d7176 Add support for modulus (Eric Aardoom)
steve authored
853
854 return osig;
855 }
856
7793a49 Remove string paths from PExpr elaboration.
steve authored
857 NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
ced7cc6 Structural logical or.
steve authored
858 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
859 const NetExpr* rise,
860 const NetExpr* fall,
861 const NetExpr* decay) const
ced7cc6 Structural logical or.
steve authored
862 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
863 NetNet*lsig = left_->elaborate_net(des, scope, 0, 0, 0, 0),
864 *rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
865
866 if (lsig == 0 || rsig == 0) return 0;
867
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
868 if (rsig->data_type() == IVL_VT_REAL ||
869 lsig->data_type() == IVL_VT_REAL) {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
870 cerr << get_fileline() << ": sorry: " << human_readable_op(op_)
871 << " is currently unsupported for real values." << endl;
872 des->errors += 1;
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
873 return 0;
874 }
ced7cc6 Structural logical or.
steve authored
875
876 NetLogic*gate;
877 switch (op_) {
878 case 'a':
badad63 All NetObj objects have lex_string base names.
steve authored
879 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
880 3, NetLogic::AND, 1);
ced7cc6 Structural logical or.
steve authored
881 break;
882 case 'o':
badad63 All NetObj objects have lex_string base names.
steve authored
883 gate = new NetLogic(scope, scope->local_symbol(),
65e9b6b Rework of internals to carry vectors through nexus instead
steve authored
884 3, NetLogic::OR, 1);
ced7cc6 Structural logical or.
steve authored
885 break;
886 default:
887 assert(0);
888 }
889
890 // The first OR gate returns 1 if the left value is true...
8184dfa Handle wide operands to logical AND.
steve authored
891 if (lsig->vector_width() > 1) {
892 NetUReduce*gate_tmp = new NetUReduce(scope, scope->local_symbol(),
893 NetUReduce::OR,
894 lsig->vector_width());
895 connect(gate_tmp->pin(1), lsig->pin(0));
896 connect(gate->pin(1), gate_tmp->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
897
898 /* The reduced logical value is a new nexus, create a
899 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
900 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
901 NetNet::IMPLICIT, 1);
a8b86ea More explicit datatype setup.
steve authored
902 tmp->data_type(IVL_VT_LOGIC);
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
903 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
904 connect(gate->pin(1), tmp->pin(0));
905
8184dfa Handle wide operands to logical AND.
steve authored
906 des->add_node(gate_tmp);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
907
ced7cc6 Structural logical or.
steve authored
908 } else {
909 connect(gate->pin(1), lsig->pin(0));
910 }
911
912 // The second OR gate returns 1 if the right value is true...
8184dfa Handle wide operands to logical AND.
steve authored
913 if (rsig->vector_width() > 1) {
914 NetUReduce*gate_tmp = new NetUReduce(scope, scope->local_symbol(),
915 NetUReduce::OR,
916 rsig->vector_width());
917 connect(gate_tmp->pin(1), rsig->pin(0));
918 connect(gate->pin(2), gate_tmp->pin(0));
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
919
920 /* The reduced logical value is a new nexus, create a
921 temporary signal to represent it. */
badad63 All NetObj objects have lex_string base names.
steve authored
922 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
923 NetNet::IMPLICIT, 1);
a8b86ea More explicit datatype setup.
steve authored
924 tmp->data_type(IVL_VT_LOGIC);
cd94019 Remove NetTmp and add NetSubnet class.
steve authored
925 tmp->local_flag(true);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
926 connect(gate->pin(2), tmp->pin(0));
927
8184dfa Handle wide operands to logical AND.
steve authored
928 des->add_node(gate_tmp);
2563e2b Revise the VVM backend to use nexus objects so that
steve authored
929
ced7cc6 Structural logical or.
steve authored
930 } else {
931 connect(gate->pin(2), rsig->pin(0));
932 }
933
934 // The output is the AND/OR of the two logic values.
badad63 All NetObj objects have lex_string base names.
steve authored
935 NetNet*osig = new NetNet(scope, scope->local_symbol(), NetNet::WIRE);
ced7cc6 Structural logical or.
steve authored
936 osig->local_flag(true);
07f345d Logical or/and return VT_LOGIC type.
steve authored
937 osig->data_type(IVL_VT_LOGIC);
ced7cc6 Structural logical or.
steve authored
938 connect(gate->pin(0), osig->pin(0));
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
939
940 gate->set_line(*this);
941 gate->rise_time(rise);
942 gate->fall_time(fall);
943 gate->decay_time(decay);
ced7cc6 Structural logical or.
steve authored
944 des->add_node(gate);
945 return osig;
946 }
947
7793a49 Remove string paths from PExpr elaboration.
steve authored
948 NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
aa8908c Multiplication all the way to simulation.
steve authored
949 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
950 const NetExpr* rise,
951 const NetExpr* fall,
952 const NetExpr* decay) const
aa8908c Multiplication all the way to simulation.
steve authored
953 {
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
954 verinum*lnum = left_->eval_const(des, scope);
955 verinum*rnum = right_->eval_const(des, scope);
956
957 /* Detect and handle the special case that both the operands
8f0c02c Spelling fixes.
steve authored
958 of the multiply are constant expressions. Evaluate the
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
959 value and make this a simple constant. */
960 if (lnum && rnum) {
961 verinum prod = *lnum * *rnum;
962 if (lwidth == 0)
963 lwidth = prod.len();
964
965 verinum res (verinum::V0, lwidth);
966 for (unsigned idx = 0
967 ; idx < prod.len() && idx < lwidth
968 ; idx += 1) {
969 res.set(idx, prod.get(idx));
970 }
971
badad63 All NetObj objects have lex_string base names.
steve authored
972 NetConst*odev = new NetConst(scope, scope->local_symbol(), res);
22efa9f Fix elaboration of multiply of two constants.
steve authored
973 des->add_node(odev);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
974 odev->rise_time(rise);
975 odev->fall_time(fall);
976 odev->decay_time(decay);
22efa9f Fix elaboration of multiply of two constants.
steve authored
977 odev->set_line(*this);
978
badad63 All NetObj objects have lex_string base names.
steve authored
979 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
980 NetNet::IMPLICIT, lwidth);
22efa9f Fix elaboration of multiply of two constants.
steve authored
981 osig->set_line(*this);
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
982 osig->local_flag(true);
22efa9f Fix elaboration of multiply of two constants.
steve authored
983 osig->data_type(IVL_VT_LOGIC);
984
985 connect(odev->pin(0), osig->pin(0));
986
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
987 return osig;
988 }
989
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
990 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
991 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
992
993 if (lsig == 0 || rsig == 0) return 0;
aa8908c Multiplication all the way to simulation.
steve authored
994
ea1f448 @caryr Real multiply in a cont. assign. is always 1 bit wide.
caryr authored
995 /* The arguments of a multiply must have the same type. */
75ad905 Generalize signals to carry types.
steve authored
996 if (lsig->data_type() != rsig->data_type()) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
997 cerr << get_fileline() << ": error: Arguments of multiply "
75ad905 Generalize signals to carry types.
steve authored
998 << "have different data types." << endl;
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
999 cerr << get_fileline() << ": : Left argument is "
75ad905 Generalize signals to carry types.
steve authored
1000 << lsig->data_type() << ", right argument is "
1001 << rsig->data_type() << "." << endl;
1002 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1003 return 0;
75ad905 Generalize signals to carry types.
steve authored
1004 }
1005
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1006 // The mult is signed if both its operands are signed.
1007 bool arith_is_signed = lsig->get_signed() && rsig->get_signed();
75ad905 Generalize signals to carry types.
steve authored
1008
4124273 Handle some special cases of unary 2's complement,
steve authored
1009 unsigned rwidth = lwidth;
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
1010 if (rwidth == 0) {
ea1f448 @caryr Real multiply in a cont. assign. is always 1 bit wide.
caryr authored
1011 /* Reals are always 1 wide and lsig/rsig types match here. */
1012 if (lsig->data_type() == IVL_VT_REAL) {
1013 rwidth = 1;
1014 lwidth = 1;
1015 } else {
1016 rwidth = lsig->vector_width() + rsig->vector_width();
1017 lwidth = rwidth;
1018 }
4bb91c4 Elaborate multiply nets with constant operands ad NetConst.
steve authored
1019 }
1020
739a183 Do sign extension of structuran nets.
steve authored
1021 if (arith_is_signed) {
1022 lsig = pad_to_width_signed(des, lsig, rwidth);
1023 rsig = pad_to_width_signed(des, rsig, rwidth);
1024 }
1025
a275133 LPM objects store only their base names.
steve authored
1026 NetMult*mult = new NetMult(scope, scope->local_symbol(), rwidth,
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1027 lsig->vector_width(),
1028 rsig->vector_width());
1029 mult->set_line(*this);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
1030 mult->rise_time(rise);
1031 mult->fall_time(fall);
1032 mult->decay_time(decay);
aa8908c Multiplication all the way to simulation.
steve authored
1033 des->add_node(mult);
1034
739a183 Do sign extension of structuran nets.
steve authored
1035 mult->set_signed( arith_is_signed );
d18934d Sign extend NetMult inputs if result is signed.
steve authored
1036
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1037 connect(mult->pin_DataA(), lsig->pin(0));
1038 connect(mult->pin_DataB(), rsig->pin(0));
aa8908c Multiplication all the way to simulation.
steve authored
1039
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1040 /* Make a signal to carry the output from the multiply. */
badad63 All NetObj objects have lex_string base names.
steve authored
1041 NetNet*osig = new NetNet(scope, scope->local_symbol(),
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1042 NetNet::IMPLICIT, rwidth);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1043 osig->data_type( lsig->data_type() );
aa8908c Multiplication all the way to simulation.
steve authored
1044 osig->local_flag(true);
99ace10 Simplified NetMult and IVL_LPM_MULT.
steve authored
1045 connect(mult->pin_Result(), osig->pin(0));
aa8908c Multiplication all the way to simulation.
steve authored
1046
1047 return osig;
1048 }
1049
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1050 NetNet* PEBinary::elaborate_net_pow_(Design*des, NetScope*scope,
1051 unsigned lwidth,
1052 const NetExpr* rise,
1053 const NetExpr* fall,
1054 const NetExpr* decay) const
1055 {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1056 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0),
1057 *rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
1058
1059 if (lsig == 0 || rsig == 0) return 0;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1060
1061 /* The arguments of a power must have the same type. */
1062 if (lsig->data_type() != rsig->data_type()) {
1063 cerr << get_fileline() << ": error: Arguments of power "
1064 << "have different data types." << endl;
1065 cerr << get_fileline() << ": : Left argument is "
1066 << lsig->data_type() << ", right argument is "
1067 << rsig->data_type() << "." << endl;
1068 des->errors += 1;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1069 return 0;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1070 }
1071
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1072 /* The power is signed if either of its operands are signed. */
85229a6 @caryr Add unsigned bit based power to continuous assignments.
caryr authored
1073 bool arith_is_signed = lsig->get_signed() || rsig->get_signed();
1074
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1075 unsigned rwidth = lwidth;
1076 if (rwidth == 0) {
1077 /* Reals are always 1 wide and lsig/rsig types match here. */
1078 if (lsig->data_type() == IVL_VT_REAL) {
1079 rwidth = 1;
1080 lwidth = 1;
1081 } else {
331faa2 @caryr Add signed bit based power to continuous assignments.
caryr authored
1082 /* This is incorrect! a * (2^b - 1) is close. */
1083 rwidth = lsig->vector_width() + rsig->vector_width();
1084 lwidth = rwidth;
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1085 }
1086 }
1087
1088 if (arith_is_signed) {
1089 lsig = pad_to_width_signed(des, lsig, rwidth);
1090 rsig = pad_to_width_signed(des, rsig, rwidth);
1091 }
1092
1093 NetPow*powr = new NetPow(scope, scope->local_symbol(), rwidth,
1094 lsig->vector_width(),
1095 rsig->vector_width());
1096 powr->set_line(*this);
1097 powr->rise_time(rise);
1098 powr->fall_time(fall);
1099 powr->decay_time(decay);
1100 des->add_node(powr);
1101
1102 powr->set_signed( arith_is_signed );
1103
1104 connect(powr->pin_DataA(), lsig->pin(0));
1105 connect(powr->pin_DataB(), rsig->pin(0));
1106
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1107 /* Make a signal to carry the output from the power. */
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1108 NetNet*osig = new NetNet(scope, scope->local_symbol(),
1109 NetNet::IMPLICIT, rwidth);
1110 osig->data_type( lsig->data_type() );
1111 osig->local_flag(true);
1112 connect(powr->pin_Result(), osig->pin(0));
1113
1114 return osig;
1115 }
1116
7793a49 Remove string paths from PExpr elaboration.
steve authored
1117 NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1118 unsigned lwidth,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
1119 const NetExpr* rise,
1120 const NetExpr* fall,
1121 const NetExpr* decay) const
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1122 {
7793a49 Remove string paths from PExpr elaboration.
steve authored
1123 NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1124
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1125 if (lsig == 0) return 0;
1126
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1127 /* Cannot shift a real value. */
1128 if (lsig->data_type() == IVL_VT_REAL) {
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1129 cerr << get_fileline() << ": error: shift operators ("
1130 << human_readable_op(op_)
1131 << ") cannot shift a real value." << endl;
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1132 des->errors += 1;
1133 return 0;
1134 }
1135
257e1f9 Support shifts and divide.
steve authored
1136 if (lsig->vector_width() > lwidth)
1137 lwidth = lsig->vector_width();
9e5ff89 Add structural reduction NAND,
steve authored
1138
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1139 bool right_flag = op_ == 'r' || op_ == 'R';
1140 bool signed_flag = op_ == 'R';
1141
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1142 /* Handle the special case of a constant shift amount. There
1143 is no reason in this case to create a gate at all, just
1144 connect the lsig to the osig with the bit positions
257e1f9 Support shifts and divide.
steve authored
1145 shifted. Use a NetPartSelect to select the parts of the
1146 left expression that survive the shift, and a NetConcat to
1147 concatenate a constant for padding. */
bf72f39 eval_const uses scope instead of a string path.
steve authored
1148 if (verinum*rval = right_->eval_const(des, scope)) {
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1149 assert(rval->is_defined());
1150 unsigned dist = rval->as_ulong();
1151
257e1f9 Support shifts and divide.
steve authored
1152 /* Very special case: constant 0 shift. Simply return
1153 the left signal again. */
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1154 if (dist == 0) return lsig;
1155
257e1f9 Support shifts and divide.
steve authored
1156 /* The construction that I'm making will ultimately
1157 connect its output to the osig here. This will be the
1158 result that I return from this function. */
badad63 All NetObj objects have lex_string base names.
steve authored
1159 NetNet*osig = new NetNet(scope, scope->local_symbol(),
4124273 Handle some special cases of unary 2's complement,
steve authored
1160 NetNet::WIRE, lwidth);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1161 osig->data_type( lsig->data_type() );
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1162 osig->local_flag(true);
1163
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1164
257e1f9 Support shifts and divide.
steve authored
1165 /* Make the constant zero's that I'm going to pad to the
1166 top or bottom of the left expression. Attach a signal
1167 to its output so that I don't have to worry about it
d9ac146 @ldoolitt Spelling fixes
ldoolitt authored
1168 later. If the left expression is less than the
257e1f9 Support shifts and divide.
steve authored
1169 desired width (and we are doing right shifts) then we
1170 can combine the expression padding with the distance
1171 padding to reduce nodes. */
1172 unsigned pad_width = dist;
1173 unsigned part_width = lwidth - dist;
1174 if (op_ == 'r' || op_ == 'R') {
1175 if (lsig->vector_width() < lwidth) {
1176 pad_width += lwidth - lsig->vector_width();
1177 part_width -= lwidth - lsig->vector_width();
1178 }
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1179 } else {
257e1f9 Support shifts and divide.
steve authored
1180
1181 /* The left net must be the same width as the
1182 result. The part select that I'm about to make relies
1183 on that. */
1184 lsig = pad_to_width(des, lsig, lwidth);
1185
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1186 }
1187
257e1f9 Support shifts and divide.
steve authored
1188 NetNet*zero = new NetNet(scope, scope->local_symbol(),
1189 NetNet::WIRE, pad_width);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1190 zero->data_type( lsig->data_type() );
257e1f9 Support shifts and divide.
steve authored
1191 zero->local_flag(true);
1192 zero->set_line(*this);
1193
31afec5 @ldoolitt Fix for pr1879226, large constant shift values
ldoolitt authored
1194 /* Padding bits are zero in most cases, but copies of
1195 * the sign bit in the case of a signed right shift */
257e1f9 Support shifts and divide.
steve authored
1196 if (op_ == 'R') {
1197 NetPartSelect*sign_bit
1198 = new NetPartSelect(lsig, lsig->vector_width()-1,
1199 1, NetPartSelect::VP);
1200 des->add_node(sign_bit);
1201 NetReplicate*sign_pad
1202 = new NetReplicate(scope, scope->local_symbol(),
1203 pad_width, pad_width);
1204 des->add_node(sign_pad);
1205 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
1206 NetNet::WIRE, 1);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1207 tmp->data_type( lsig->data_type() );
326329d Set some missing local flags.
steve authored
1208 tmp->local_flag(true);
1209 tmp->set_line(*this);
257e1f9 Support shifts and divide.
steve authored
1210 connect(sign_bit->pin(0), tmp->pin(0));
1211 connect(sign_bit->pin(0), sign_pad->pin(1));
1212
1213 connect(zero->pin(0), sign_pad->pin(0));
1214
1215 } else {
1216 NetConst*zero_c = new NetConst(scope, scope->local_symbol(),
1217 verinum(verinum::V0, pad_width));
1218 des->add_node(zero_c);
1219 connect(zero->pin(0), zero_c->pin(0));
1220 }
1221
31afec5 @ldoolitt Fix for pr1879226, large constant shift values
ldoolitt authored
1222 /* If all data bits get shifted away, connect the zero or
1223 * padding bits directly to output, and stop before building the
1224 * concatenation. */
1225 if (dist >= lwidth) {
1226 connect(osig->pin(0), zero->pin(0));
1227 return osig;
1228 }
1229
257e1f9 Support shifts and divide.
steve authored
1230 /* Make a concatenation operator that will join the
1231 part-selected right expression at the pad values. */
1232 NetConcat*cc = new NetConcat(scope, scope->local_symbol(),
1233 lwidth, 2);
1234 cc->set_line(*this);
1235 des->add_node(cc);
1236 connect(cc->pin(0), osig->pin(0));
1237
1238 /* Make the part select of the left expression and
1ff31db @caryr Add real comparisons in continuous assignments.
caryr authored
1239 connect it to the LSB or MSB of the concatenation,
257e1f9 Support shifts and divide.
steve authored
1240 depending on the direction of the shift. */
1241 NetPartSelect*part;
1242
1243 switch (op_) {
1244 case 'l': // Left shift === {lsig, zero}
1245 part = new NetPartSelect(lsig, 0, part_width,
1246 NetPartSelect::VP);
1247 connect(cc->pin(1), zero->pin(0));
1248 connect(cc->pin(2), part->pin(0));
1249 break;
1250 case 'R':
1251 case 'r': // right-shift === {zero, lsig}
1252 part = new NetPartSelect(lsig, dist, part_width,
1253 NetPartSelect::VP);
1254 connect(cc->pin(1), part->pin(0));
1255 connect(cc->pin(2), zero->pin(0));
1256 break;
1257 default:
1258 assert(0);
1259 }
1260
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
1261 part->set_line(*this);
1262 part->rise_time(rise);
1263 part->fall_time(fall);
1264 part->decay_time(decay);
257e1f9 Support shifts and divide.
steve authored
1265 des->add_node(part);
1266
4b829bf Get argument widths right for shift results.
steve authored
1267 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1268 cerr << get_fileline() << ": debug: Elaborate shift "
4b829bf Get argument widths right for shift results.
steve authored
1269 << "(" << op_ << ") as concatenation of "
1270 << pad_width << " zeros with " << part_width
1271 << " bits of expression." << endl;
1272 }
1273
257e1f9 Support shifts and divide.
steve authored
1274 /* Attach a signal to the part select output (NetConcat
1275 input) */
1276 NetNet*tmp = new NetNet(scope, scope->local_symbol(),
1277 NetNet::WIRE, part_width);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1278 tmp->data_type( lsig->data_type() );
257e1f9 Support shifts and divide.
steve authored
1279 tmp->local_flag(true);
1280 tmp->set_line(*this);
1281 connect(part->pin(0), tmp->pin(0));
1282
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1283 return osig;
1284 }
1285
9e5ff89 Add structural reduction NAND,
steve authored
1286 // Calculate the number of useful bits for the shift amount,
1287 // and elaborate the right_ expression as the shift amount.
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1288 unsigned dwid = 0;
61195c5 Harmless fixup of warnings.
steve authored
1289 while ((1U << dwid) < lwidth)
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1290 dwid += 1;
1291
7793a49 Remove string paths from PExpr elaboration.
steve authored
1292 NetNet*rsig = right_->elaborate_net(des, scope, dwid, 0, 0, 0);
fac1cc5 @caryr Add user function synth and clean up expression code.
caryr authored
1293
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1294 if (rsig == 0) return 0;
1295
db851c2 @caryr Add more error checking for operators that cannot use real values.
caryr authored
1296 /* You cannot shift a value by a real amount. */
1297 if (rsig->data_type() == IVL_VT_REAL) {
1298 cerr << get_fileline() << ": error: shift operators "
1299 "cannot shift by a real value." << endl;
1300 des->errors += 1;
1301 return 0;
1302 }
1303
9e5ff89 Add structural reduction NAND,
steve authored
1304 // Make the shift device itself, and the output
1305 // NetNet. Connect the Result output pins to the osig signal
a275133 LPM objects store only their base names.
steve authored
1306 NetCLShift*gate = new NetCLShift(scope, scope->local_symbol(),
257e1f9 Support shifts and divide.
steve authored
1307 lwidth, rsig->vector_width(),
3dbc07f Implement signed divide and signed right shift in nets.
steve authored
1308 right_flag, signed_flag);
10d25d2 @caryr Support delays for all operators in a continuous assignments.
caryr authored
1309 gate->set_line(*this);
1310 gate->rise_time(rise);
1311 gate->fall_time(fall);
1312 gate->decay_time(decay);
257e1f9 Support shifts and divide.
steve authored
1313 des->add_node(gate);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1314
badad63 All NetObj objects have lex_string base names.
steve authored
1315 NetNet*osig = new NetNet(scope, scope->local_symbol(),
9e5ff89 Add structural reduction NAND,
steve authored
1316 NetNet::WIRE, lwidth);
5e8a1bd @caryr Add power operator (**) for real values in a continuous assignment.
caryr authored
1317 osig->data_type( lsig->data_type() );
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1318 osig->local_flag(true);
257e1f9 Support shifts and divide.
steve authored
1319 osig->set_signed(signed_flag);
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1320
257e1f9 Support shifts and divide.
steve authored
1321 connect(osig->pin(0), gate->pin_Result());
9e5ff89 Add structural reduction NAND,
steve authored
1322
1323 // Connect the lsig (the left expression) to the Data input,
ca488df Handle LPM shifts.
steve authored
1324 // and pad it if necessary. The lwidth is the width of the
1325 // NetCLShift gate, and the D input must match.
1326 if (lsig->vector_width() < lwidth)
1327 lsig = pad_to_width(des, lsig, lwidth);
1328
1329 assert(lsig->vector_width() <= lwidth);
257e1f9 Support shifts and divide.
steve authored
1330 connect(lsig->pin(0), gate->pin_Data());
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1331
9e5ff89 Add structural reduction NAND,
steve authored
1332 // Connect the rsig (the shift amount expression) to the
1333 // Distance input.
257e1f9 Support shifts and divide.
steve authored
1334 connect(rsig->pin(0), gate->pin_Distance());
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1335
257e1f9 Support shifts and divide.
steve authored
1336 if (debug_elaborate) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1337 cerr << get_fileline() << ": debug: "
257e1f9 Support shifts and divide.
steve authored
1338 << "Elaborate LPM_SHIFT: width="<<gate->width()
1339 << ", swidth="<< gate->width_dist() << endl;
1340 }
1624afe Add support for the LPM_CLSHIFT device.
steve authored
1341
1342 return osig;
1343 }
1344
cdb99e7 Elaborate net repeat concatenations.
steve authored
1345 /*
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1346 * This method elaborates a call to a function in the context of a
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1347 * continuous assignment. The definition of the function contains a
1348 * list of the ports, and an output port. The NetEUFunc that I create
1349 * here has a port for all the input ports and the output port. The
1350 * ports are connected by pins.
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1351 */
5d1d99a Handle signed magnitude compare all the
steve authored
1352 NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
1353 unsigned width,
58f182a Node delays can be more general expressions in structural contexts.
steve authored
1354 const NetExpr* rise,
1355 const NetExpr* fall,
1356 const NetExpr* decay,
5d1d99a Handle signed magnitude compare all the
steve authored
1357 Link::strength_t drive0,
1358 Link::strength_t drive1) const
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1359 {
1360 unsigned errors = 0;
1361 unsigned func_pins = 0;
1362
ddd36ec Rework the heirarchical identifier parse syntax and pform
steve authored
1363 if (path_.front().name[0] == '$')
80f30be Add support for system functions in continuous assignments.
steve authored
1364 return elaborate_net_sfunc_(des, scope,
1365 width, rise, fall, decay,
1366 drive0, drive1);
7f67afe Add support for $unsigned.
steve authored
1367
5d1d99a Handle signed magnitude compare all the
steve authored
1368
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1369 /* Look up the function definition. */
1370 NetFuncDef*def = des->find_function(scope, path_);
1371 if (def == 0) {
7975e14 @steveicarus LineInfo uses perm_string for path.
authored
1372 cerr << get_fileline() << ": error: No function " << path_ <<
c7d97f4 Properly evaluate scope path expressions.
steve authored
1373 " in this context (" << scope_path(scope) << ")." << endl;
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1374 des->errors += 1;
1375 return 0;
1376 }
1377
1378 NetScope*dscope = def->scope();
1379 assert(dscope);
1380
47d6503 @ldoolitt Spelling fixes
ldoolitt authored
1381 /* This must be a function that returns a signal. */
5472b27 Rewire/generalize parsing an elaboration of
steve authored
1382 assert(def->return_sig());
1383
b7c2bd4 Add the NetUserFunc netlist node.
steve authored
1384 /* check the validity of the parameters. */
1385 if (! check_call_matches_definition_(des, dscope))
1386 return 0;