Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 462 lines (413 sloc) 13.982 kb
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
1 /*
2 * Copyright (c) 1999 Stephen Williams (steve@icarus.com)
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 #if !defined(WINNT)
206b37e Fix NetConst being set to zero width, and clean
steve authored
20 #ident "$Id: elab_net.cc,v 1.3 1999/11/05 21:45:19 steve Exp $"
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
21 #endif
22
23 # include "PExpr.h"
24 # include "netlist.h"
25
26 /*
27 * Elaborating binary operations generally involves elaborating the
28 * left and right expressions, then making an output wire and
29 * connecting the lot together with the right kind of gate.
30 */
31 NetNet* PEBinary::elaborate_net(Design*des, const string&path,
32 unsigned width,
33 unsigned long rise,
34 unsigned long fall,
35 unsigned long decay) const
36 {
37 switch (op_) {
38 case '+':
39 case '-':
40 return elaborate_net_add_(des, path, width, rise, fall, decay);
206b37e Fix NetConst being set to zero width, and clean
steve authored
41 case 'E':
42 case 'e':
43 case 'n':
44 return elaborate_net_cmp_(des, path, width, rise, fall, decay);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
45 }
46
47 NetNet*lsig = left_->elaborate_net(des, path, width, 0, 0, 0),
48 *rsig = right_->elaborate_net(des, path, width, 0, 0, 0);
49 if (lsig == 0) {
50 cerr << get_line() << ": error: Cannot elaborate ";
51 left_->dump(cerr);
52 cerr << endl;
53 return 0;
54 }
55 if (rsig == 0) {
56 cerr << get_line() << ": error: Cannot elaborate ";
57 right_->dump(cerr);
58 cerr << endl;
59 return 0;
60 }
61
62 NetNet*osig;
63 NetNode*gate;
64 NetNode*gate_t;
65
66 switch (op_) {
67 case '^': // XOR
68 assert(lsig->pin_count() == rsig->pin_count());
69 osig = new NetNet(des->local_symbol(path), NetNet::WIRE,
70 lsig->pin_count());
71 osig->local_flag(true);
72 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
73 gate = new NetLogic(des->local_symbol(path), 3,
74 NetLogic::XOR);
75 connect(gate->pin(1), lsig->pin(idx));
76 connect(gate->pin(2), rsig->pin(idx));
77 connect(gate->pin(0), osig->pin(idx));
78 gate->rise_time(rise);
79 gate->fall_time(fall);
80 gate->decay_time(decay);
81 des->add_node(gate);
82 }
83 des->add_signal(osig);
84 break;
85
86 case '&': // AND
87 assert(lsig->pin_count() == rsig->pin_count());
88 osig = new NetNet(des->local_symbol(path), NetNet::WIRE,
89 lsig->pin_count());
90 osig->local_flag(true);
91 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
92 gate = new NetLogic(des->local_symbol(path), 3,
93 NetLogic::AND);
94 connect(gate->pin(1), lsig->pin(idx));
95 connect(gate->pin(2), rsig->pin(idx));
96 connect(gate->pin(0), osig->pin(idx));
97 gate->rise_time(rise);
98 gate->fall_time(fall);
99 gate->decay_time(decay);
100 des->add_node(gate);
101 }
102 des->add_signal(osig);
103 break;
104
105 case '|': // Bitwise OR
106 assert(lsig->pin_count() == rsig->pin_count());
107 osig = new NetNet(des->local_symbol(path), NetNet::WIRE,
108 lsig->pin_count());
109 osig->local_flag(true);
110 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
111 gate = new NetLogic(des->local_symbol(path), 3,
112 NetLogic::OR);
113 connect(gate->pin(1), lsig->pin(idx));
114 connect(gate->pin(2), rsig->pin(idx));
115 connect(gate->pin(0), osig->pin(idx));
116 gate->rise_time(rise);
117 gate->fall_time(fall);
118 gate->decay_time(decay);
119 des->add_node(gate);
120 }
121 des->add_signal(osig);
122 break;
123
124 case 'a': // && (logical AND)
125 gate = new NetLogic(des->local_symbol(path), 3, NetLogic::AND);
126
127 // The first OR gate returns 1 if the left value is true...
128 if (lsig->pin_count() > 1) {
129 gate_t = new NetLogic(des->local_symbol(path),
130 1+lsig->pin_count(), NetLogic::OR);
131 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
132 connect(gate_t->pin(idx+1), lsig->pin(idx));
133 connect(gate->pin(1), gate_t->pin(0));
134 des->add_node(gate_t);
135 } else {
136 connect(gate->pin(1), lsig->pin(0));
137 }
138
139 // The second OR gate returns 1 if the right value is true...
140 if (rsig->pin_count() > 1) {
141 gate_t = new NetLogic(des->local_symbol(path),
142 1+rsig->pin_count(), NetLogic::OR);
143 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
144 connect(gate_t->pin(idx+1), rsig->pin(idx));
145 connect(gate->pin(2), gate_t->pin(0));
146 des->add_node(gate_t);
147 } else {
148 connect(gate->pin(2), rsig->pin(0));
149 }
150
151 // The output is the AND of the two logic values.
152 osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
153 osig->local_flag(true);
154 connect(gate->pin(0), osig->pin(0));
155 des->add_signal(osig);
156 gate->rise_time(rise);
157 gate->fall_time(fall);
158 gate->decay_time(decay);
159 des->add_node(gate);
160 break;
161
162 case 'E': // === (Case equals)
163 case 'e': // ==
164 case 'n': // !=
206b37e Fix NetConst being set to zero width, and clean
steve authored
165 assert(0);
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
166 break;
167
168 case '+':
169 assert(0);
170 break;
171
172 case 'l':
173 case 'r':
174 cerr << get_line() << ": sorry: combinational shift"
175 " not supported here." << endl;
176 des->errors += 1;
177 osig = 0;
178 break;
179 default:
180 cerr << get_line() << ": internal error: unsupported"
181 " combinational operator (" << op_ << ")." << endl;
182 des->errors += 1;
183 osig = 0;
184 }
185
186 if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
187 delete tmp;
188 if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
189 delete tmp;
190
191 return osig;
192 }
193
194 /*
195 * Elaborate the structural +/- as an AddSub object. Connect DataA and
196 * DataB to the parameters, and connect the output signal to the
197 * Result. In this context, the device is a combinational adder with
198 * fixed direction, so leave Add_Sub unconnected and set the
199 * LPM_Direction property.
200 */
201 NetNet* PEBinary::elaborate_net_add_(Design*des, const string&path,
202 unsigned lwidth,
203 unsigned long rise,
204 unsigned long fall,
205 unsigned long decay) const
206 {
207 NetNet*lsig = left_->elaborate_net(des, path, lwidth, 0, 0, 0),
208 *rsig = right_->elaborate_net(des, path, lwidth, 0, 0, 0);
209 if (lsig == 0) {
210 cerr << get_line() << ": error: Cannot elaborate ";
211 left_->dump(cerr);
212 cerr << endl;
213 return 0;
214 }
215 if (rsig == 0) {
216 cerr << get_line() << ": error: Cannot elaborate ";
217 right_->dump(cerr);
218 cerr << endl;
219 return 0;
220 }
221
222 NetNet*osig;
223 NetNode*gate;
224 NetNode*gate_t;
225
226 string name = des->local_symbol(path);
227 unsigned width = lsig->pin_count();
228 if (rsig->pin_count() > lsig->pin_count())
229 width = rsig->pin_count();
230
231 // Make the adder as wide as the widest operand
232 osig = new NetNet(des->local_symbol(path), NetNet::WIRE, width);
233 NetAddSub*adder = new NetAddSub(name, width);
234
235 // Connect the adder to the various parts.
236 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1)
237 connect(lsig->pin(idx), adder->pin_DataA(idx));
238 for (unsigned idx = 0 ; idx < rsig->pin_count() ; idx += 1)
239 connect(rsig->pin(idx), adder->pin_DataB(idx));
240 for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
241 connect(osig->pin(idx), adder->pin_Result(idx));
242
243 gate = adder;
244 des->add_signal(osig);
245 gate->rise_time(rise);
246 gate->fall_time(fall);
247 gate->decay_time(decay);
248 des->add_node(gate);
249
250 switch (op_) {
251 case '+':
252 gate->attribute("LPM_Direction", "ADD");
253 break;
254 case '-':
255 gate->attribute("LPM_Direction", "SUB");
256 break;
257 }
258
259 if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
260 delete tmp;
261 if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
262 delete tmp;
263
264 return osig;
265 }
266
267 /*
206b37e Fix NetConst being set to zero width, and clean
steve authored
268 * Elaborate the various binary comparison operators.
269 */
270 NetNet* PEBinary::elaborate_net_cmp_(Design*des, const string&path,
271 unsigned lwidth,
272 unsigned long rise,
273 unsigned long fall,
274 unsigned long decay) const
275 {
276 NetNet*lsig = left_->elaborate_net(des, path, 0, 0, 0, 0),
277 *rsig = right_->elaborate_net(des, path, 0, 0, 0, 0);
278 if (lsig == 0) {
279 cerr << get_line() << ": error: Cannot elaborate ";
280 left_->dump(cerr);
281 cerr << endl;
282 return 0;
283 }
284 if (rsig == 0) {
285 cerr << get_line() << ": error: Cannot elaborate ";
286 right_->dump(cerr);
287 cerr << endl;
288 return 0;
289 }
290
291 if (lsig->pin_count() != rsig->pin_count()) {
292 cerr << get_line() << ": internal error: Cannot match "
293 "structural net widths " << lsig->pin_count() <<
294 " and " << rsig->pin_count() << "." << endl;
295 delete lsig;
296 delete rsig;
297 des->errors += 1;
298 return 0;
299 }
300
301 NetNet*osig = new NetNet(des->local_symbol(path), NetNet::WIRE);
302 osig->local_flag(true);
303
304 NetNode*gate;
305 NetNode*gate_t;
306
307 switch (op_) {
308 case 'E': // Case equals (===)
309 // The comparison generates gates to bitwise compare
310 // each pair, and AND all the comparison results.
311 gate = new NetLogic(des->local_symbol(path),
312 1+lsig->pin_count(),
313 NetLogic::AND);
314 connect(gate->pin(0), osig->pin(0));
315 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
316 gate_t = new NetCaseCmp(des->local_symbol(path));
317 connect(gate_t->pin(1), lsig->pin(idx));
318 connect(gate_t->pin(2), rsig->pin(idx));
319 connect(gate_t->pin(0), gate->pin(idx+1));
320 des->add_node(gate_t);
321
322 // Attach a label to this intermediate wire
323 NetNet*tmp = new NetNet(des->local_symbol(path),
324 NetNet::WIRE);
325 tmp->local_flag(true);
326 connect(gate_t->pin(0), tmp->pin(0));
327 des->add_signal(tmp);
328 }
329 break;
330
331
332 case 'e': // ==
333 gate = new NetLogic(des->local_symbol(path),
334 1+lsig->pin_count(),
335 NetLogic::AND);
336 connect(gate->pin(0), osig->pin(0));
337 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
338 gate_t = new NetLogic(des->local_symbol(path), 3,
339 NetLogic::XNOR);
340 connect(gate_t->pin(1), lsig->pin(idx));
341 connect(gate_t->pin(2), rsig->pin(idx));
342 connect(gate_t->pin(0), gate->pin(idx+1));
343 des->add_node(gate_t);
344 }
345 break;
346
347 case 'n': // !=
348 gate = new NetLogic(des->local_symbol(path),
349 1+lsig->pin_count(),
350 NetLogic::OR);
351 connect(gate->pin(0), osig->pin(0));
352 for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
353 gate_t = new NetLogic(des->local_symbol(path), 3,
354 NetLogic::XOR);
355 connect(gate_t->pin(1), lsig->pin(idx));
356 connect(gate_t->pin(2), rsig->pin(idx));
357 connect(gate_t->pin(0), gate->pin(idx+1));
358 des->add_node(gate_t);
359 }
360 break;
361
362 default:
363 assert(0);
364 }
365
366 des->add_signal(osig);
367 gate->rise_time(rise);
368 gate->fall_time(fall);
369 gate->decay_time(decay);
370 des->add_node(gate);
371
372 return osig;
373 }
374
375 /*
376 * Elaborate a number as a NetConst object.
377 */
378 NetNet* PENumber::elaborate_net(Design*des, const string&path,
379 unsigned lwidth,
380 unsigned long rise,
381 unsigned long fall,
382 unsigned long decay) const
383 {
384 unsigned width = value_->len();
385 if ((lwidth > 0) && (lwidth < width))
386 width = lwidth;
387
388 NetNet*net = new NetNet(des->local_symbol(path),
389 NetNet::IMPLICIT, width);
390 net->local_flag(true);
391 for (unsigned idx = 0 ; idx < width ; idx += 1) {
392 NetConst*tmp = new NetConst(des->local_symbol(path),
393 value_->get(idx));
394 des->add_node(tmp);
395 connect(net->pin(idx), tmp->pin(0));
396 }
397
398 des->add_signal(net);
399 return net;
400 }
401
402
403 /*
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
404 * Elaborate the ternary operator in a netlist by creating a LPM_MUX
405 * with width matching the result, size == 2 and 1 select input.
406 */
407 NetNet* PETernary::elaborate_net(Design*des, const string&path,
408 unsigned width,
409 unsigned long rise,
410 unsigned long fall,
411 unsigned long decay) const
412 {
413 NetNet* expr_sig = expr_->elaborate_net(des, path, 0, 0, 0, 0);
414 NetNet* tru_sig = tru_->elaborate_net(des, path, width, 0, 0, 0);
415 NetNet* fal_sig = fal_->elaborate_net(des, path, width, 0, 0, 0);
416 if (expr_sig == 0 || tru_sig == 0 || fal_sig == 0) {
417 des->errors += 1;
418 return 0;
419 }
420
421 assert(tru_sig->pin_count() == fal_sig->pin_count());
422 assert(width == tru_sig->pin_count());
423 assert(expr_sig->pin_count() == 1);
424
425 NetNet*sig = new NetNet(des->local_symbol(path), NetNet::WIRE,
426 tru_sig->pin_count());
427 sig->local_flag(true);
428
429 NetMux*mux = new NetMux(des->local_symbol(path), width, 2, 1);
430 connect(mux->pin_Sel(0), expr_sig->pin(0));
431
432 for (unsigned idx = 0 ; idx < width ; idx += 1) {
433 connect(mux->pin_Result(idx), sig->pin(idx));
434 connect(mux->pin_Data(idx,0), fal_sig->pin(idx));
435 connect(mux->pin_Data(idx,1), tru_sig->pin(idx));
436 }
437 }
438
439 /*
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
440 * $Log: elab_net.cc,v $
206b37e Fix NetConst being set to zero width, and clean
steve authored
441 * Revision 1.3 1999/11/05 21:45:19 steve
442 * Fix NetConst being set to zero width, and clean
443 * up elaborate_set_cmp_ for NetEBinary.
444 *
cb5fc54 Patch to synthesize unary ~ and the ternary operator.
steve authored
445 * Revision 1.2 1999/11/04 03:53:26 steve
446 * Patch to synthesize unary ~ and the ternary operator.
447 * Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
448 *
449 * Add the LPM_MUX device, and integrate it with the
450 * ternary synthesis from Larry. Replace the lpm_mux
451 * generator in t-xnf.cc to use XNF EQU devices to
452 * put muxs into function units.
453 *
454 * Rewrite elaborate_net for the PETernary class to
455 * also use the LPM_MUX device.
456 *
e1bbbe5 Include subtraction in LPM_ADD_SUB device.
steve authored
457 * Revision 1.1 1999/10/31 20:08:24 steve
458 * Include subtraction in LPM_ADD_SUB device.
459 *
460 */
461
Something went wrong with that request. Please try again.