Make C style comments work in false/suppressed ifdef/etc. blocks.
[iverilog.git] / xnfio.cc
blob9bf99c727e1a30a8582e21ff389c87878041b11a
1 /*
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)
8 * any later version.
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
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: xnfio.cc,v 1.30 2007/03/22 16:08:18 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
27 # include "functor.h"
28 # include "netlist.h"
29 # include "netmisc.h"
31 class xnfio_f : public functor_t {
33 public:
34 void signal(Design*des, NetNet*sig);
35 void lpm_compare(Design*des, NetCompare*dev);
37 private:
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())
44 return false;
46 return true;
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();
62 assert(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;
72 return 0;
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()) {
82 NetLogic*tmp;
83 if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
84 continue;
86 // Try to use an existing BUF as an OBUF. This moves the
87 // BUF into the IOB.
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"),
93 verinum("OBUF:O,I"));
94 return tmp;
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"));
108 return tmp;
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"));
121 return tmp;
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"));
130 return tmp;
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(),
137 2, NetLogic::BUF);
138 des->add_node(buf);
140 buf->attribute(perm_string::literal("XNF-LCA"), verinum("OBUF:O,I"));
142 // Put the buffer between this signal and the rest of the
143 // netlist.
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(),
153 NetNet::WIRE);
154 tmp->local_flag(true);
155 connect(buf->pin(1), tmp->pin(0));
158 return buf;
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)
166 return;
167 if (count_inputs(buf->pin(1)) != 1)
168 return;
169 /* For now, only support OUTFF. */
170 if (buf->type() != NetLogic::BUF)
171 return;
173 Link*drv = find_next_output(&buf->pin(1));
174 assert(drv);
176 /* Make sure the device is a FF with width 1. */
177 NetFF*ff = dynamic_cast<NetFF*>(drv->get_obj());
178 if (ff == 0)
179 return;
180 if (ff->width() != 1)
181 return;
182 if (ff->attribute(perm_string::literal("LPM_FFType")) != verinum("DFF"))
183 return;
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));
188 delete buf;
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)
194 names[idx] = "";
196 if (ff->attribute(perm_string::literal("Clock:LPM_Polarity")) == verinum("INVERT"))
197 names[ff->pin_Clock().get_pin()] = "~C";
198 else
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];
207 delete[]names;
209 ff->attribute(perm_string::literal("XNF-LCA"), lname);
212 static void make_ibuf(Design*des, NetNet*net)
214 NetScope*scope = net->scope();
215 assert(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()) {
227 NetLogic*tmp;
228 if ((tmp = dynamic_cast<NetLogic*>(idx->get_obj())) == 0)
229 continue;
231 if (tmp->attribute(perm_string::literal("XNF-LCA")) != verinum())
232 continue;
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"));
240 return;
245 // I give up, create an IBUF.
246 NetLogic*buf = new NetLogic(scope, scope->local_symbol(),
247 2, NetLogic::BUF);
248 des->add_node(buf);
250 buf->attribute(perm_string::literal("XNF-LCA"), verinum("IBUF:O,I"));
252 // Put the buffer between this signal and the rest of the
253 // netlist.
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(),
264 NetNet::WIRE);
265 connect(buf->pin(0), tmp->pin(0));
269 void xnfio_f::signal(Design*des, NetNet*net)
271 if (! is_a_pad(net))
272 return;
274 assert(net->pin_count() == 1);
275 string pattr = net->attribute(perm_string::literal("PAD")).as_string();
277 switch (pattr[0]) {
278 case 'i':
279 case 'I':
280 make_ibuf(des, net);
281 break;
282 case 'o':
283 case 'O': {
284 NetLogic*buf = make_obuf(des, net);
285 if (buf == 0) break;
286 absorb_OFF(des, buf);
287 break;
290 // FIXME: Only IPAD and OPAD supported. Need to
291 // add support for IOPAD.
292 default:
293 assert(0);
294 break;
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))
304 return;
306 return;
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)
316 return false;
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())
326 return false;
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,
335 NetLogic::NOR);
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));
339 delete dev;
340 des->add_node(sub);
341 return true;
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,
348 NetLogic::OR);
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));
352 delete dev;
353 des->add_node(sub);
354 return true;
357 return false;
360 void xnfio(Design*des)
362 xnfio_f xnfio_obj;
363 des->functor(&xnfio_obj);
367 * $Log: xnfio.cc,v $
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
384 * Spelling fixes.
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.