2 * Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
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)
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.
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
20 #ident "$Id: xnfio.cc,v 1.30 2007/03/22 16:08:18 steve Exp $"
31 class xnfio_f
: public functor_t
{
34 void signal(Design
*des
, NetNet
*sig
);
35 void lpm_compare(Design
*des
, NetCompare
*dev
);
38 bool compare_sideb_const(Design
*des
, NetCompare
*dev
);
41 static bool is_a_pad(const NetNet
*net
)
43 if (net
->attribute(perm_string::literal("PAD")) == verinum())
50 * The xnfio function looks for the PAD signals in the design, and
51 * generates the needed IOB devices to handle being connected to the
52 * actual FPGA PAD. This will add items to the netlist if needed.
54 * FIXME: If there is a DFF connected to the pad, try to convert it
55 * to an IO DFF instead. This would save a CLB, and it is
56 * really lame to not do the obvious optimization.
59 static NetLogic
* make_obuf(Design
*des
, NetNet
*net
)
61 NetScope
* scope
= net
->scope();
64 assert(net
->pin_count() == 1);
66 /* FIXME: If there is nothing internally driving this PAD, I
67 can connect the PAD to a pullup and disconnect it from the
68 rest of the circuit. This would save routing resources. */
69 if (count_outputs(net
->pin(0)) <= 0) {
70 cerr
<< net
->get_line() << ":warning: No outputs to OPAD: "
71 << net
->name() << endl
;
75 assert(count_outputs(net
->pin(0)) > 0);
77 /* Look for an existing OBUF connected to this signal. If it
78 is there, then no need to add one. */
79 Nexus
*nex
= net
->pin(0).nexus();
80 for (Link
*idx
= nex
->first_nlink()
81 ; idx
; idx
= idx
->next_nlink()) {
83 if ((tmp
= dynamic_cast<NetLogic
*>(idx
->get_obj())) == 0)
86 // Try to use an existing BUF as an OBUF. This moves the
88 if ((tmp
->type() == NetLogic::BUF
)
89 && (count_inputs(tmp
->pin(0)) == 0)
90 && (count_outputs(tmp
->pin(0)) == 1)
91 && (idx
->get_pin() == 0) ) {
92 tmp
->attribute(perm_string::literal("XNF-LCA"),
97 // Try to use an existing INV as an OBUF. Certain
98 // technologies support inverting the input of an OBUF,
99 // which looks just like an inverter. This uses the
100 // available resources of an IOB to optimize away an
101 // otherwise expensive inverter.
102 if ((tmp
->type() == NetLogic::NOT
)
103 && (count_inputs(tmp
->pin(0)) == 0)
104 && (count_outputs(tmp
->pin(0)) == 1)
105 && (idx
->get_pin() == 0) ) {
106 tmp
->attribute(perm_string::literal("XNF-LCA"),
107 verinum("OBUF:O,~I"));
111 // Try to use an existing bufif1 as an OBUFT. Of course
112 // this will only work if the output of the bufif1 is
113 // connected only to the pad. Handle bufif0 the same
114 // way, but the T input is inverted.
115 if ((tmp
->type() == NetLogic::BUFIF1
)
116 && (count_inputs(tmp
->pin(0)) == 0)
117 && (count_outputs(tmp
->pin(0)) == 1)
118 && (idx
->get_pin() == 0) ) {
119 tmp
->attribute(perm_string::literal("XNF-LCA"),
120 verinum("OBUFT:O,I,~T"));
124 if ((tmp
->type() == NetLogic::BUFIF0
)
125 && (count_inputs(tmp
->pin(0)) == 0)
126 && (count_outputs(tmp
->pin(0)) == 1)
127 && (idx
->get_pin() == 0) ) {
128 tmp
->attribute(perm_string::literal("XNF-LCA"),
129 verinum("OBUFT:O,I,T"));
134 // Can't seem to find a way to rearrange the existing netlist,
135 // so I am stuck creating a new buffer, the OBUF.
136 NetLogic
*buf
= new NetLogic(scope
, scope
->local_symbol(),
140 buf
->attribute(perm_string::literal("XNF-LCA"), verinum("OBUF:O,I"));
142 // Put the buffer between this signal and the rest of the
144 connect(net
->pin(0), buf
->pin(1));
145 net
->pin(0).unlink();
146 connect(net
->pin(0), buf
->pin(0));
148 // It is possible, in putting an OBUF between net and the rest
149 // of the netlist, to create a ring without a signal. Detect
150 // this case and create a new signal.
151 if (count_signals(buf
->pin(1)) == 0) {
152 NetNet
*tmp
= new NetNet(scope
, scope
->local_symbol(),
154 tmp
->local_flag(true);
155 connect(buf
->pin(1), tmp
->pin(0));
161 static void absorb_OFF(Design
*des
, NetLogic
*buf
)
163 /* If the nexus connects is not a simple point-to-point link,
164 then I can't drag it into the IOB. Give up. */
165 if (count_outputs(buf
->pin(1)) != 1)
167 if (count_inputs(buf
->pin(1)) != 1)
169 /* For now, only support OUTFF. */
170 if (buf
->type() != NetLogic::BUF
)
173 Link
*drv
= find_next_output(&buf
->pin(1));
176 /* Make sure the device is a FF with width 1. */
177 NetFF
*ff
= dynamic_cast<NetFF
*>(drv
->get_obj());
180 if (ff
->width() != 1)
182 if (ff
->attribute(perm_string::literal("LPM_FFType")) != verinum("DFF"))
185 /* Connect the flip-flop output to the buffer output and
186 delete the buffer. The XNF OUTFF can buffer the pin. */
187 connect(ff
->pin_Q(0), buf
->pin(0));
190 /* Finally, build up an XNF-LCA value that defines this
191 devices as an OUTFF and gives each pin an XNF name. */
192 char**names
= new char*[ff
->pin_count()];
193 for (unsigned idx
= 0 ; idx
< ff
->pin_count() ; idx
+= 1)
196 if (ff
->attribute(perm_string::literal("Clock:LPM_Polarity")) == verinum("INVERT"))
197 names
[ff
->pin_Clock().get_pin()] = "~C";
199 names
[ff
->pin_Clock().get_pin()] = "C";
201 names
[ff
->pin_Data(0).get_pin()] = "D";
202 names
[ff
->pin_Q(0).get_pin()] = "Q";
204 string lname
= string("OUTFF:") + names
[0];
205 for (unsigned idx
= 1 ; idx
< ff
->pin_count() ; idx
+= 1)
206 lname
= lname
+ "," + names
[idx
];
209 ff
->attribute(perm_string::literal("XNF-LCA"), lname
);
212 static void make_ibuf(Design
*des
, NetNet
*net
)
214 NetScope
*scope
= net
->scope();
217 assert(net
->pin_count() == 1);
218 // XXXX For now, require at least one input.
219 assert(count_inputs(net
->pin(0)) > 0);
221 /* Look for an existing BUF connected to this signal and
222 suitably connected that I can use it as an IBUF. */
224 Nexus
*nex
= net
->pin(0).nexus();
225 for (Link
*idx
= nex
->first_nlink()
226 ; idx
; idx
= idx
->next_nlink()) {
228 if ((tmp
= dynamic_cast<NetLogic
*>(idx
->get_obj())) == 0)
231 if (tmp
->attribute(perm_string::literal("XNF-LCA")) != verinum())
234 // Found a BUF, it is only usable if the only input is
235 // the signal and there are no other inputs.
236 if ((tmp
->type() == NetLogic::BUF
) &&
237 (count_inputs(tmp
->pin(1)) == 1) &&
238 (count_outputs(tmp
->pin(1)) == 0)) {
239 tmp
->attribute(perm_string::literal("XNF-LCA"), verinum("IBUF:O,I"));
245 // I give up, create an IBUF.
246 NetLogic
*buf
= new NetLogic(scope
, scope
->local_symbol(),
250 buf
->attribute(perm_string::literal("XNF-LCA"), verinum("IBUF:O,I"));
252 // Put the buffer between this signal and the rest of the
254 connect(net
->pin(0), buf
->pin(0));
255 net
->pin(0).unlink();
256 connect(net
->pin(0), buf
->pin(1));
258 // It is possible, in putting an OBUF between net and the rest
259 // of the netlist, to create a ring without a signal. Detect
260 // this case and create a new signal.
261 if (count_signals(buf
->pin(0)) == 0) {
262 NetNet
*tmp
= new NetNet(scope
,
263 scope
->local_symbol(),
265 connect(buf
->pin(0), tmp
->pin(0));
269 void xnfio_f::signal(Design
*des
, NetNet
*net
)
274 assert(net
->pin_count() == 1);
275 string pattr
= net
->attribute(perm_string::literal("PAD")).as_string();
284 NetLogic
*buf
= make_obuf(des
, net
);
286 absorb_OFF(des
, buf
);
290 // FIXME: Only IPAD and OPAD supported. Need to
291 // add support for IOPAD.
299 * Attempt some XNF specific optimizations on comparators.
301 void xnfio_f::lpm_compare(Design
*des
, NetCompare
*dev
)
303 if (compare_sideb_const(des
, dev
))
309 bool xnfio_f::compare_sideb_const(Design
*des
, NetCompare
*dev
)
311 /* Even if side B is all constant, if there are more than 4
312 signals on side A we will not be able to fit the operation
313 into a function unit, so we might as well accept a
314 comparator. Give up. */
315 if (dev
->width() > 4)
318 NetScope
*scope
= dev
->scope();
320 verinum
side (verinum::V0
, dev
->width());
322 /* Is the B side all constant? */
323 for (unsigned idx
= 0 ; idx
< dev
->width() ; idx
+= 1) {
325 if (! dev
->pin_DataB(idx
).nexus()->drivers_constant())
328 side
.set(idx
, dev
->pin_DataB(idx
).nexus()->driven_value());
331 /* Handle the special case of comparing A to 0. Use an N-input
332 NOR gate to return 0 if any of the bits is not 0. */
333 if ((side
.as_ulong() == 0) && (count_inputs(dev
->pin_AEB()) > 0)) {
334 NetLogic
*sub
= new NetLogic(scope
, dev
->name(), dev
->width()+1,
336 connect(sub
->pin(0), dev
->pin_AEB());
337 for (unsigned idx
= 0 ; idx
< dev
->width() ; idx
+= 1)
338 connect(sub
->pin(idx
+1), dev
->pin_DataA(idx
));
344 /* Handle the special case of comparing A to 0. Use an N-input
345 NOR gate to return 0 if any of the bits is not 0. */
346 if ((side
.as_ulong() == 0) && (count_inputs(dev
->pin_ANEB()) > 0)) {
347 NetLogic
*sub
= new NetLogic(scope
, dev
->name(), dev
->width()+1,
349 connect(sub
->pin(0), dev
->pin_ANEB());
350 for (unsigned idx
= 0 ; idx
< dev
->width() ; idx
+= 1)
351 connect(sub
->pin(idx
+1), dev
->pin_DataA(idx
));
360 void xnfio(Design
*des
)
363 des
->functor(&xnfio_obj
);
368 * Revision 1.30 2007/03/22 16:08:18 steve
369 * Spelling fixes from Larry
371 * Revision 1.29 2004/02/20 18:53:36 steve
372 * Addtrbute keys are perm_strings.
374 * Revision 1.28 2004/02/18 17:11:58 steve
375 * Use perm_strings for named langiage items.
377 * Revision 1.27 2003/06/24 01:38:03 steve
378 * Various warnings fixed.
380 * Revision 1.26 2003/03/06 00:28:42 steve
381 * All NetObj objects have lex_string base names.
383 * Revision 1.25 2003/01/30 16:23:08 steve
386 * Revision 1.24 2003/01/14 21:16:18 steve
387 * Move strstream to ostringstream for compatibility.
389 * Revision 1.23 2002/08/12 01:35:01 steve
390 * conditional ident string using autoconfig.
392 * Revision 1.22 2002/06/25 01:33:22 steve
393 * Cache calculated driven value.
395 * Revision 1.21 2002/06/24 01:49:39 steve
396 * Make link_drive_constant cache its results in
397 * the Nexus, to improve cprop performance.
399 * Revision 1.20 2002/05/23 03:08:52 steve
400 * Add language support for Verilog-2001 attribute
401 * syntax. Hook this support into existing $attribute
402 * handling, and add number and void value types.
404 * Add to the ivl_target API new functions for access
405 * of complex attributes attached to gates.
407 * Revision 1.19 2001/10/20 05:21:51 steve
408 * Scope/module names are char* instead of string.
410 * Revision 1.18 2001/07/25 03:10:50 steve
411 * Create a config.h.in file to hold all the config
412 * junk, and support gcc 3.0. (Stephan Boettcher)
414 * Revision 1.17 2000/11/20 00:58:40 steve
415 * Add support for supply nets (PR#17)
417 * Revision 1.16 2000/10/07 19:45:43 steve
418 * Put logic devices into scopes.
420 * Revision 1.15 2000/06/25 19:59:42 steve
421 * Redesign Links to include the Nexus class that
422 * carries properties of the connected set of links.
424 * Revision 1.14 2000/05/07 04:37:56 steve
425 * Carry strength values from Verilog source to the
426 * pform and netlist for gates.
428 * Change vvm constants to use the driver_t to drive
429 * a constant value. This works better if there are
430 * multiple drivers on a signal.
432 * Revision 1.13 2000/05/02 00:58:12 steve
433 * Move signal tables to the NetScope class.
435 * Revision 1.12 2000/04/20 00:28:03 steve
436 * Catch some simple identity compareoptimizations.
438 * Revision 1.11 2000/02/23 02:56:56 steve
439 * Macintosh compilers do not support ident.
441 * Revision 1.10 1999/12/11 05:45:41 steve
442 * Fix support for attaching attributes to primitive gates.
444 * Revision 1.9 1999/11/27 19:07:58 steve
445 * Support the creation of scopes.
447 * Revision 1.8 1999/11/19 05:02:15 steve
448 * Handle inverted clock into OUTFF.
450 * Revision 1.7 1999/11/19 03:02:25 steve
451 * Detect flip-flops connected to opads and turn
452 * them into OUTFF devices. Inprove support for
453 * the XNF-LCA attribute in the process.
455 * Revision 1.6 1999/11/18 02:58:37 steve
456 * Handle (with a warning) unconnected opads.
458 * Revision 1.5 1999/11/02 04:55:01 steve
459 * repair the sense of T from bufif01
461 * Revision 1.4 1999/11/02 01:43:55 steve
462 * Fix iobuf and iobufif handling.
464 * Revision 1.3 1999/10/09 17:52:27 steve
465 * support XNF OBUFT devices.
467 * Revision 1.2 1999/07/17 22:01:14 steve
468 * Add the functor interface for functor transforms.
470 * Revision 1.1 1998/12/07 04:53:17 steve
471 * Generate OBUF or IBUF attributes (and the gates
472 * to garry them) where a wire is a pad. This involved
473 * figuring out enough of the netlist to know when such
474 * was needed, and to generate new gates and signales
475 * to handle what's missing.