Add -D to iverilog-vpi and update documentation.
[iverilog.git] / t-xnf.cc
blobe6bf20bc8f12f114ffa9d17a70fd231039e8b457
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: t-xnf.cc,v 1.52 2004/02/20 18:53:36 steve Exp $"
21 #endif
23 # include "config.h"
25 # include <iostream>
27 /* XNF BACKEND
28 * This target supports generating Xilinx Netlist Format netlists for
29 * use by Xilinx tools, and other tools that accepts Xilinx designs.
31 * The code generator automatically detects ports to top level modules
32 * and generates SIG records that make the XNF usable as a schematic.
34 * FLAGS
35 * The XNF backend uses the following flags from the command line to
36 * affect the generated file:
38 * part=<foo>
39 * Specify the part type. The part string is written into the
40 * PART record. Valid types are defined by Xilinx or the
41 * receiving tools.
43 * ncf=<path>
44 * Specify the path to a NCF file. This is an OUTPUT file into
45 * which the code generator will write netlist constraints that
46 * relate to pin assignments, CLB placement, etc. If this flag is
47 * not given, no NCF file will be written.
49 * WIRE ATTRIBUTES
51 * PAD = <io><n>
52 * Tell the XNF generator that this wire goes to a PAD. The <io>
53 * is a single character that tells the direction, and <n> is the
54 * pin number. For example, "o31" is output on pin 31. The PAD
55 * attribute is not practically connected to a vector, as all the
56 * bits would go to the same pad.
58 * NODE ATTRIBUTES
60 * XNF-LCA = <lname>:<pin>,<pin>...
61 * Specify the LCA library part type for the gate. The lname
62 * is the name of the symbol to use (i.e. DFF) and the comma
63 * separated list is the names of the pins, in the order they
64 * appear in the Verilog source. If the name is prefixed with a
65 * tilde (~) then the pin is inverted, and the proper "INV" token
66 * will be added to the PIN record.
68 * This attribute can override even the typical generation of
69 * gates that one might naturally expect of the code generator,
70 * but may be used by the optimizers for placing parts.
72 * An example is "XNF-LCA=OBUF:O,~I". This attribute means that
73 * the object is an OBUF. Pin 0 is called "O", and pin 1 is
74 * called "I". In addition, pin 1 is inverted.
77 # include "netlist.h"
78 # include "target.h"
79 # include <fstream>
80 # include <sstream>
82 verinum::V link_get_ival(const Link&lnk)
84 const Nexus*nex = lnk.nexus();
85 for (const Link*cur = nex->first_nlink()
86 ; cur ; cur = cur->next_nlink()) {
87 if (cur == &lnk)
88 continue;
90 if (dynamic_cast<const NetNet*>(cur->get_obj()))
91 return cur->nexus()->get_init();
95 return verinum::Vx;
98 class target_xnf : public target_t {
100 public:
101 bool start_design(const Design*);
102 int end_design(const Design*);
103 void memory(const NetMemory*);
104 void signal(const NetNet*);
106 void lpm_add_sub(const NetAddSub*);
107 void lpm_compare(const NetCompare*);
108 void lpm_compare_eq_(ostream&os, const NetCompare*);
109 void lpm_compare_ge_(ostream&os, const NetCompare*);
110 void lpm_compare_le_(ostream&os, const NetCompare*);
111 void lpm_ff(const NetFF*);
112 void lpm_mux(const NetMux*);
113 void lpm_ram_dq(const NetRamDq*);
115 bool net_const(const NetConst*);
116 void logic(const NetLogic*);
117 bool bufz(const NetBUFZ*);
118 void udp(const NetUDP*);
120 private:
121 static string mangle(const string&);
122 static string mangle(perm_string);
123 static string choose_sig_name(const Link*lnk);
124 static void draw_pin(ostream&os, const string&name,
125 const Link&lnk);
126 static void draw_sym_with_lcaname(ostream&os, string lca,
127 const NetNode*net);
128 static void draw_xor(ostream&os, const NetAddSub*, unsigned idx);
129 enum adder_type {FORCE0, LOWER, DOUBLE, LOWER_W_CO, EXAMINE_CI };
130 static void draw_carry(ostream&os, const NetAddSub*, unsigned idx,
131 enum adder_type);
133 ofstream out_;
134 ofstream ncf_;
138 * This function takes a signal name and mangles it into an equivalent
139 * name that is suitable to the XNF format.
141 string target_xnf::mangle(const string&name)
143 string result;
144 for (unsigned idx = 0 ; idx < name.length() ; idx += 1)
145 switch (name[idx]) {
146 case '.':
147 result = result + "/";
148 break;
149 default:
150 result = result + name[idx];
151 break;
154 return result;
157 string target_xnf::mangle(perm_string name)
159 return mangle(string(name));
163 * This method takes a signal and pin number as a nexus. Scan the
164 * nexus to decide which name to use if there are lots of attached
165 * signals.
167 string target_xnf::choose_sig_name(const Link*lnk)
169 return mangle( string(lnk->nexus()->name()) );
172 void target_xnf::draw_pin(ostream&os, const string&name,
173 const Link&lnk)
175 bool inv = false;
176 string use_name = name;
177 if (use_name[0] == '~') {
178 inv = true;
179 use_name = use_name.substr(1);
182 char type=0;
183 switch (lnk.get_dir()) {
184 case Link::INPUT:
185 case Link::PASSIVE:
186 type = 'I';
187 break;
188 case Link::OUTPUT:
189 type = 'O';
190 break;
192 assert(type);
194 os << " PIN, " << use_name << ", " << type << ", " <<
195 choose_sig_name(&lnk);
196 if (inv) os << ",,INV";
197 os << endl;
200 static string scrape_pin_name(string&list)
202 unsigned idx = list.find(',');
203 string name = list.substr(0, idx);
204 list = list.substr(idx+1);
205 return name;
209 * This method draws an LCA item based on the XNF-LCA attribute
210 * given. The LCA attribute gives enough information to completely
211 * draw the node in XNF, which is pretty handy at this point.
213 void target_xnf::draw_sym_with_lcaname(ostream&os, string lca,
214 const NetNode*net)
216 unsigned idx = lca.find(':');
217 string lcaname = lca.substr(0, idx);
218 lca = lca.substr(idx+1);
220 os << "SYM, " << mangle(net->name()) << ", " << lcaname
221 << ", LIBVER=2.0.0" << endl;
223 for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
224 string usename = scrape_pin_name(lca);
225 if (usename == "") continue;
226 draw_pin(os, usename, net->pin(idx));
229 os << "END" << endl;
232 bool target_xnf::start_design(const Design*des)
234 out_.open(des->get_flag("-o"), ios::out | ios::trunc);
236 string ncfpath = des->get_flag("ncf");
237 if (ncfpath != "")
238 ncf_.open(ncfpath.c_str());
240 out_ << "LCANET,6" << endl;
241 out_ << "PROG,verilog,$Name: $,\"Icarus Verilog\"" << endl;
242 ncf_ << "# Generated by Icarus Verilog $Name: $" << endl;
244 if (des->get_flag("part") != 0) {
245 out_ << "PART," << des->get_flag("part") << endl;
246 ncf_ << "CONFIG PART=" << des->get_flag("part") << ";" << endl;
249 return true;
252 int target_xnf::end_design(const Design*)
254 out_ << "EOF" << endl;
255 ncf_.close();
256 return 0;
259 void scrape_pad_info(string str, char&dir, unsigned&num)
261 // Get rid of leading white space
262 while (str[0] == ' ')
263 str = str.substr(1);
265 // Get the direction letter
266 switch (str[0]) {
267 case 'b':
268 case 'B':
269 dir = 'B';
270 break;
271 case 'o':
272 case 'O':
273 dir = 'O';
274 break;
275 case 'i':
276 case 'I':
277 dir = 'I';
278 break;
279 case 't':
280 case 'T':
281 dir = 'T';
282 break;
283 default:
284 dir = '?';
285 break;
288 // Get the number part.
289 str = str.substr(1);
290 unsigned val = 0;
291 while (str.size() && isdigit(str[0])) {
292 val = val * 10 + (str[0]-'0');
293 str = str.substr(1);
295 num = val;
299 * Memories are handled by the lpm_ram_dq method, so there is nothing
300 * to do here.
302 void target_xnf::memory(const NetMemory*)
307 * Look for signals that have attributes that are pertinent to XNF
308 * files. The most obvious are those that have the PAD attribute.
310 * Individual signals are easy, the pad description is a letter
311 * followed by a decimal number that is the pin.
313 * The PAD attribute for a vector is a comma separated pin
314 * descriptions, that enumerate the pins from most significant to
315 * least significant.
317 void target_xnf::signal(const NetNet*net)
320 /* Look for signals that are ports to the root module. If they
321 are, the write a SIG record and generate a pin name so that
322 this module can be used as a macro. */
324 if (const NetScope*scope = net->scope()) do {
326 if (scope->parent())
327 break;
329 if (net->port_type() == NetNet::NOT_A_PORT)
330 break;
332 string mname = mangle(net->name());
333 string pname = mname.substr(mname.find('/')+1, mname.length());
335 if (net->pin_count() == 1) {
336 out_ << "SIG, " << mangle(net->name()) << ", PIN="
337 << pname << endl;
339 } else for (unsigned idx = 0; idx < net->pin_count(); idx += 1) {
340 out_ << "SIG, " << mangle(net->name()) << "<" << idx
341 << ">, PIN=" << pname << idx << endl;
344 } while (0);
347 /* Now look to see if a PAD attribute is attached, and if so
348 write out PAD information to the XNF and the ncf files. */
350 string pad = net->attribute(perm_string::literal("PAD")).as_string();
351 if (pad == "")
352 return;
354 if (net->pin_count() > 1) {
355 cerr << "Signal ``" << net->name() << "'' with PAD=" <<
356 pad << " is a vector." << endl;
357 return;
360 char dir;
361 unsigned num;
362 scrape_pad_info(pad, dir, num);
363 out_ << "EXT, " << mangle(net->name()) << ", " << dir
364 << ", " << num << endl;
366 ncf_ << "# Assignment to pin " << num << " (DIR=" << dir <<
367 ") by $attribute(" << net->name() << ", \"PAD\", \"" <<
368 pad << "\")" << endl;
369 ncf_ << "NET " << mangle(net->name()) << " LOC=P" << num << ";"
370 << endl;
373 void target_xnf::draw_xor(ostream &os, const NetAddSub*gate, unsigned idx)
375 string name = mangle(gate->name());
376 string name_add = name;
377 string name_cout = name + "/COUT";
379 // We only need to pick up the
380 // carry if we are not the 0 bit. (We know it is 0).
381 os << "SYM, " << name_add << "<" << (idx+0) << ">, XOR, "
382 "LIBVER=2.0.0" << endl;
383 draw_pin(os, "O", gate->pin_Result(idx));
384 draw_pin(os, "I0", gate->pin_DataA(idx));
385 draw_pin(os, "I1", gate->pin_DataB(idx));
386 if (idx > 0) {
387 os << " PIN, I2, I, " << name_cout << "<" <<
388 idx << ">" << endl;
390 os << "END" << endl;
393 void target_xnf::draw_carry(ostream &os, const NetAddSub*gate, unsigned idx,
394 enum adder_type type)
396 string name = mangle(gate->name());
398 string name_cy4 = name + "/CY";
399 string name_cym = name + "/CM";
400 string name_cout = name + "/COUT";
402 os << "SYM, " << name_cy4 << "<" << idx << ">, CY4, "
403 "LIBVER=2.0.0" << endl;
405 // Less significant bit addends, if any
406 if ( type == LOWER || type == DOUBLE || type == LOWER_W_CO ) {
407 draw_pin(os, "A0", gate->pin_DataA(idx));
408 draw_pin(os, "B0", gate->pin_DataB(idx));
411 // More significant bit addends, if any
412 if ( type == DOUBLE ) {
413 draw_pin(os, "A1", gate->pin_DataA(idx+1));
414 draw_pin(os, "B1", gate->pin_DataB(idx+1));
417 // All but FORCE0 cells have carry input
418 if ( type != FORCE0 ) {
419 os << " PIN, CIN, I, " << name_cout << "<" << idx << ">" << endl;
422 // Connect the Cout0 to a signal so that I can connect
423 // it to the adder.
424 switch (type) {
425 case LOWER:
426 case DOUBLE:
427 os << " PIN, COUT0, O, " << name_cout << "<" << (idx+1) <<
428 ">" << endl;
429 break;
430 case EXAMINE_CI:
431 case LOWER_W_CO:
432 draw_pin(os, "COUT0", gate->pin_Cout());
433 break;
435 default:
436 assert(0);
439 // Connect the Cout, this will connect to the next Cin
440 if ( type == FORCE0 || type == DOUBLE ) {
441 unsigned int to = (type==FORCE0)?(0):(idx+2);
442 os << " PIN, COUT, O, " << name_cout << "<" << to <<
443 ">" << endl;
446 // These are the mode inputs from the CY_xx pseudo-device
447 for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
448 os << " PIN, C" << cn << ", I, " << name << "/C"
449 << cn << "<" << (idx) << ">" << endl;
451 os << "END" << endl;
453 // On to the CY_xx pseudo-device itself
454 os << "SYM, " << name_cym << "<" << (idx) << ">, ";
455 switch (type) {
456 case FORCE0:
457 os << "CY4_37, CYMODE=FORCE-0" << endl;
458 break;
459 case LOWER:
460 os << "CY4_01, CYMODE=ADD-F-CI" << endl;
461 break;
462 case LOWER_W_CO:
463 os << "CY4_01, CYMODE=ADD-F-CI" << endl;
464 break;
465 case DOUBLE:
466 os << "CY4_02, CYMODE=ADD-FG-CI" << endl;
467 break;
468 case EXAMINE_CI:
469 os << "CY4_42, CYMODE=EXAMINE-CI" << endl;
470 break;
472 for (unsigned cn = 0 ; cn < 8 ; cn += 1) {
473 os << " PIN, C" << cn << ", O, " << name << "/C"
474 << cn << "<" << (idx) << ">" << endl;
476 os << "END" << endl;
480 * This function makes an adder out of carry logic symbols. It makes
481 * as many 2 bit adders as are possible, then the top bit is made into
482 * a 1-bit adder (with carry in) in the F unit. The low carry is
483 * initialized with the FORCE-0 configuration of a carry unit below
484 * the 0 bit. This takes up the carry logic of the CLB below, but not
485 * the G function.
487 * References:
488 * XNF 6.1 Specification
489 * Application note XAPP013
490 * Xilinx Libraries Guide, Chapter 12
492 void target_xnf::lpm_add_sub(const NetAddSub*gate)
494 unsigned width = gate->width();
496 /* Make the force-0 carry mode object to initialize the bottom
497 bits of the carry chain. Label this with the width instead
498 of the bit position so that symbols don't clash. */
500 draw_carry(out_, gate, width+1, FORCE0);
503 /* Now make the 2 bit adders that chain from the cin
504 initializer and up. Save the tail bits for later. */
505 for (unsigned idx = 0 ; idx < width-2 ; idx += 2)
506 draw_carry(out_, gate, idx, DOUBLE);
508 /* Always have one or two tail bits. The situation gets a
509 little tricky if we want the carry output, so handle that
510 here.
512 If the carry-out is connected, and there are an even number
513 of data bits, we need to see the cout from the CLB. This is
514 done by configuring the top CLB CY device as ADD-FG-CI (to
515 activate cout) and create an extra CLB CY device on top of
516 the carry chain configured EXAMINE-CI to put the carry into
517 the G function block.
519 IF the carry-out is connected and there are an odd number
520 of data bits, then the top CLB can be configured to carry
521 the top bit in the F unit and deliver the carry out through
522 the G unit.
524 If the carry-out is not connected, then configure this top
525 CLB as ADD-F-CI. The draw_xor for the top bit will include
526 the F carry if needed. */
528 if (gate->pin_Cout().is_linked()) {
529 if (width%2 == 0) {
530 draw_carry(out_, gate, width-2, DOUBLE);
531 draw_carry(out_, gate, width, EXAMINE_CI);
532 } else {
533 draw_carry(out_, gate, width-1, LOWER_W_CO);
536 } else {
537 if (width%2 == 0)
538 draw_carry(out_, gate, width-2, LOWER);
539 else
540 draw_carry(out_, gate, width-1, LOWER);
543 /* Now draw all the single bit (plus carry in) adders from XOR
544 gates. This puts the F and G units to use. */
545 for (unsigned idx = 0 ; idx < width ; idx += 1)
546 draw_xor(out_, gate, idx);
551 * In XNF, comparators are done differently depending on the type of
552 * comparator being implemented. So, here we dispatch to the correct
553 * code generator.
555 void target_xnf::lpm_compare(const NetCompare*dev)
557 if (dev->pin_AEB().is_linked() || dev->pin_ANEB().is_linked()) {
558 lpm_compare_eq_(out_, dev);
559 return;
562 if (dev->pin_AGEB().is_linked()) {
563 lpm_compare_ge_(out_, dev);
564 return;
567 if (dev->pin_ALEB().is_linked()) {
568 lpm_compare_le_(out_, dev);
569 return;
572 assert(0);
576 * To compare that vectors are equal (identity comparator) generate
577 * XNOR gates to compare each pair of bits, then generate an AND gate
578 * to combine the bitwise results. This is pretty much the best way to
579 * do an identity compare in Xilinx CLBs.
581 void target_xnf::lpm_compare_eq_(ostream&os, const NetCompare*dev)
583 string mname = mangle(dev->name());
585 /* Draw XNOR gates for each bit pair. These gates to the
586 bitwise comparison. */
587 for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) {
588 os << "SYM, " << mname << "/cmp<" << idx << ">, "
589 << "XNOR, LIBVER=2.0.0" << endl;
590 os << " PIN, O, O, " << mname << "/bit<" << idx << ">"
591 << endl;
592 draw_pin(os, "I0", dev->pin_DataA(idx));
593 draw_pin(os, "I1", dev->pin_DataB(idx));
594 os << "END" << endl;
597 /* Now draw an AND gate to combine all the bitwise
598 comparisons. If there are more the 5 bits of data, then we
599 are going to have generate a nested AND to combine the
600 results. */
602 if (dev->width() > 5) {
603 for (unsigned idx = 0 ; idx < dev->width() ; idx += 5) {
605 if ((idx+1) >= dev->width()) break;
606 os << "SYM, " << mname << "/nest<" << idx
607 << ">, AND, LIBVER=2.0.0" << endl;
609 os << " PIN, O, O, " << mname << "/nbit<" << idx
610 << ">" << endl;
612 os << " PIN, I0, I, " << mname << "/bit<" << idx+0
613 << ">" << endl;
614 os << " PIN, I1, I, " << mname << "/bit<" << idx+1
615 << ">" << endl;
616 if ((idx+2) >= dev->width()) goto gate_out;
617 os << " PIN, I2, I, " << mname << "/bit<" << idx+2
618 << ">" << endl;
619 if ((idx+3) >= dev->width()) goto gate_out;
620 os << " PIN, I3, I, " << mname << "/bit<" << idx+3
621 << ">" << endl;
622 if ((idx+4) >= dev->width()) goto gate_out;
623 os << " PIN, I4, I, " << mname << "/bit<" << idx+4
624 << ">" << endl;
625 gate_out:
626 os << "END" << endl;
629 /* Draw an AND gate if this is an EQ result, or a NAND
630 gate of this is a NEQ result. */
632 if (dev->pin_AEB().is_linked()) {
633 assert( ! dev->pin_ANEB().is_linked());
634 os << "SYM, " << mname << ", AND, LIBVER=2.0.0" << endl;
635 draw_pin(os, "O", dev->pin_AEB());
637 } else {
638 assert( dev->pin_ANEB().is_linked());
639 os << "SYM, " << mname << ", NAND, LIBVER=2.0.0" << endl;
640 draw_pin(os, "O", dev->pin_ANEB());
643 for (unsigned idx = 0 ; idx < dev->width() ; idx += 5) {
644 if ((idx+1) == dev->width())
645 os << " PIN, I" << idx/5 << ", I, " << mname
646 << "/bit<" << idx << ">" << endl;
647 else
648 os << " PIN, I" << idx/5 << ", I, " << mname
649 << "/nbit<" << idx << ">" << endl;
651 os << "END" << endl;
653 } else {
654 if (dev->pin_AEB().is_linked()) {
655 assert( ! dev->pin_ANEB().is_linked());
656 os << "SYM, " << mname << ", AND, LIBVER=2.0.0" << endl;
657 draw_pin(os, "O", dev->pin_AEB());
659 } else {
660 assert( dev->pin_ANEB().is_linked());
661 os << "SYM, " << mname << ", NAND, LIBVER=2.0.0" << endl;
662 draw_pin(os, "O", dev->pin_ANEB());
665 for (unsigned idx = 0 ; idx < dev->width() ; idx += 1) {
666 os << " PIN, I" << idx << ", I, " << mname << "/bit<"
667 << idx << ">" << endl;
669 os << "END" << endl;
673 void target_xnf::lpm_compare_ge_(ostream&os, const NetCompare*dev)
675 cerr << "XXXX GE not supported yet" << endl;
678 void target_xnf::lpm_compare_le_(ostream&os, const NetCompare*dev)
680 cerr << "XXXX LE not supported yet" << endl;
683 void target_xnf::lpm_ff(const NetFF*net)
685 string type = net->attribute(perm_string::literal("LPM_FFType")).as_string();
686 if (type == "") type = "DFF";
688 // XXXX For now, only support DFF
689 assert(type == "DFF");
691 string lcaname = net->attribute(perm_string::literal("XNF-LCA")).as_string();
692 if (lcaname != "") {
693 draw_sym_with_lcaname(out_, lcaname, net);
694 return;
697 assert(net->attribute(perm_string::literal("XNF-LCA")) == verinum(""));
699 /* Create a DFF object for each bit of width. The symbol name
700 has the index number appended so that read XNF may be able
701 to buss them. If the NetNet objects connected to the Q
702 output of the DFF have an initial value, the write an INIT=
703 parameter to set the power-up value. */
705 for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
707 verinum::V ival = link_get_ival(net->pin_Q(idx));
709 out_ << "SYM, " << mangle(net->name()) << "<" << idx << ">, DFF, ";
711 switch (ival) {
712 case verinum::V0:
713 out_ << "INIT=R, ";
714 break;
715 case verinum::V1:
716 out_ << "INIT=S, ";
717 break;
719 default:
720 break;
723 out_ << "LIBVER=2.0.0" << endl;
724 draw_pin(out_, "Q", net->pin_Q(idx));
725 draw_pin(out_, "D", net->pin_Data(idx));
727 if (net->attribute(perm_string::literal("Clock:LPM_Polarity")) == verinum("INVERT"))
728 draw_pin(out_, "~C", net->pin_Clock());
729 else
730 draw_pin(out_, "C", net->pin_Clock());
732 if (net->pin_Enable().is_linked())
733 draw_pin(out_, "CE", net->pin_Enable());
735 out_ << "END" << endl;
740 * Generate an LPM_MUX.
742 * XXXX NOTE: For now, this only supports combinational LPM_MUX
743 * devices that have a single select input. These are typically
744 * generated from ?: expressions.
746 void target_xnf::lpm_mux(const NetMux*net)
748 assert(net->sel_width() == 1);
749 assert(net->size() == 2);
751 for (unsigned idx = 0 ; idx < net->width() ; idx += 1) {
753 out_ << "SYM, " << mangle(net->name()) << "<" << idx << ">,"
754 << " EQN, EQN=(I0 * I2) + (~I0 * I1)" << endl;
756 draw_pin(out_, "I0", net->pin_Sel(0));
757 draw_pin(out_, "I1", net->pin_Data(idx,0));
758 draw_pin(out_, "I2", net->pin_Data(idx,1));
759 draw_pin(out_, "O", net->pin_Result(idx));
761 out_ << "END" << endl;
766 void target_xnf::lpm_ram_dq(const NetRamDq*ram)
768 assert(ram->count_partners() == 1);
770 for (unsigned idx = 0 ; idx < ram->width() ; idx += 1) {
771 out_ << "SYM, " << mangle(ram->name())
772 << "<" << idx << ">, RAMS" << endl;
774 draw_pin(out_, "O", ram->pin_Q(idx));
775 draw_pin(out_, "D", ram->pin_Data(idx));
776 draw_pin(out_, "WE", ram->pin_WE());
777 draw_pin(out_, "WCLK", ram->pin_InClock());
778 for (unsigned adr = 0 ; adr < ram->awidth() ; adr += 1) {
779 ostringstream tmp;
780 tmp << "A" << adr;
781 draw_pin(out_, tmp.str(), ram->pin_Address(adr));
784 out_ << "END" << endl;
788 bool target_xnf::net_const(const NetConst*c)
790 unsigned x_bits = 0;
791 for (unsigned idx = 0 ; idx < c->pin_count() ; idx += 1) {
792 verinum::V v=c->value(idx);
793 const Link& lnk = c->pin(idx);
795 switch (v) {
796 case verinum::V0:
797 out_ << " PWR, 0, " << choose_sig_name(&lnk) << endl;
798 break;
799 case verinum::V1:
800 out_ << " PWR, 1, " << choose_sig_name(&lnk) << endl;
801 break;
802 case verinum::Vz:
803 break;
804 default:
805 x_bits += 1;
806 if (x_bits == 1)
807 cerr << "xnf: error: Unknown (x) const bit value"
808 << " assigned to " << choose_sig_name(&lnk)
809 << endl;
810 break;
814 return x_bits == 0;
818 * The logic gates I know so far can be translated directly into XNF
819 * standard symbol types. This is a fairly obvious transformation.
821 void target_xnf::logic(const NetLogic*net)
823 // The XNF-LCA attribute overrides anything I might guess
824 // about this object.
825 string lca = net->attribute(perm_string::literal("XNF-LCA")).as_string();
826 if (lca != "") {
827 draw_sym_with_lcaname(out_, lca, net);
828 return;
831 out_ << "SYM, " << mangle(net->name()) << ", ";
832 switch (net->type()) {
833 case NetLogic::AND:
834 out_ << "AND";
835 break;
836 case NetLogic::BUF:
837 out_ << "BUF";
838 break;
839 case NetLogic::NAND:
840 out_ << "NAND";
841 break;
842 case NetLogic::NOR:
843 out_ << "NOR";
844 break;
845 case NetLogic::NOT:
846 out_ << "INV";
847 break;
848 case NetLogic::OR:
849 out_ << "OR";
850 break;
851 case NetLogic::XNOR:
852 out_ << "XNOR";
853 break;
854 case NetLogic::XOR:
855 out_ << "XOR";
856 break;
857 case NetLogic::BUFIF0:
858 case NetLogic::BUFIF1:
859 out_ << "TBUF";
860 break;
861 default:
862 cerr << "internal error: XNF: Unhandled logic type." << endl;
863 break;
865 out_ << ", LIBVER=2.0.0" << endl;
867 /* All of these kinds of devices have an output on pin 0. */
868 draw_pin(out_, "O", net->pin(0));
870 /* Most devices have inputs called I<N> for all the remaining
871 pins. The TBUF devices are slightly different, but
872 essentially the same structure. */
873 switch (net->type()) {
875 case NetLogic::BUFIF0:
876 assert(net->pin_count() == 3);
877 draw_pin(out_, "I", net->pin(1));
878 draw_pin(out_, "~T", net->pin(2));
879 break;
881 case NetLogic::BUFIF1:
882 assert(net->pin_count() == 3);
883 draw_pin(out_, "I", net->pin(1));
884 draw_pin(out_, "T", net->pin(2));
885 break;
887 default:
888 if (net->pin_count() == 2) {
889 draw_pin(out_, "I", net->pin(1));
890 } else for (unsigned idx = 1; idx < net->pin_count(); idx += 1) {
891 string name = "I";
892 assert(net->pin_count() <= 11);
893 name += (char)('0'+idx-1);
894 draw_pin(out_, name, net->pin(idx));
896 break;
899 out_ << "END" << endl;
902 bool target_xnf::bufz(const NetBUFZ*net)
904 static int warned_once=0;
905 if (!warned_once) {
906 cerr << "0:0: internal warning: BUFZ objects found "
907 << "in XNF netlist." << endl;
908 cerr << "0:0: : I'll make BUFs for them."
909 << endl;
910 warned_once=1;
912 out_ << "SYM, " << mangle(net->name()) << ", BUF, LIBVER=2.0.0" << endl;
913 assert(net->pin_count() == 2);
914 draw_pin(out_, "O", net->pin(0));
915 draw_pin(out_, "I", net->pin(1));
916 out_ << "END" << endl;
918 return true;
921 void target_xnf::udp(const NetUDP*net)
923 string lca = net->attribute(perm_string::literal("XNF-LCA")).as_string();
925 // I only know how to draw a UDP if it has the XNF-LCA
926 // attribute attached to it.
927 if (lca == "") {
928 cerr << "I don't understand this UDP." << endl;
929 return;
932 draw_sym_with_lcaname(out_, lca, net);
935 static target_xnf target_xnf_obj;
937 extern const struct target tgt_xnf = { "xnf", &target_xnf_obj };
940 * $Log: t-xnf.cc,v $
941 * Revision 1.52 2004/02/20 18:53:36 steve
942 * Addtrbute keys are perm_strings.
944 * Revision 1.51 2004/02/18 17:11:58 steve
945 * Use perm_strings for named langiage items.
947 * Revision 1.50 2003/11/10 20:59:04 steve
948 * Design::get_flag returns const char* instead of string.
950 * Revision 1.49 2003/07/05 20:42:08 steve
951 * Fix some enumeration warnings.
953 * Revision 1.48 2003/06/24 01:38:03 steve
954 * Various warnings fixed.
956 * Revision 1.47 2003/01/30 16:23:08 steve
957 * Spelling fixes.
959 * Revision 1.46 2003/01/14 21:16:18 steve
960 * Move strstream to ostringstream for compatibility.
962 * Revision 1.45 2002/08/12 01:35:01 steve
963 * conditional ident string using autoconfig.
965 * Revision 1.44 2002/05/23 03:08:52 steve
966 * Add language support for Verilog-2001 attribute
967 * syntax. Hook this support into existing $attribute
968 * handling, and add number and void value types.
970 * Add to the ivl_target API new functions for access
971 * of complex attributes attached to gates.
973 * Revision 1.43 2001/07/25 03:10:50 steve
974 * Create a config.h.in file to hold all the config
975 * junk, and support gcc 3.0. (Stephan Boettcher)
977 * Revision 1.42 2001/06/30 20:11:15 steve
978 * typo in CYMODE=EXAMINE-CI string.
980 * Revision 1.41 2001/03/27 03:31:06 steve
981 * Support error code from target_t::end_design method.
983 * Revision 1.40 2001/02/10 03:22:49 steve
984 * Report errors when XNF code has constant X values. (PR#128)
986 * Revision 1.39 2000/11/29 23:15:54 steve
987 * More informative BUFZ warning.
989 * Revision 1.38 2000/11/29 02:54:49 steve
990 * Add XNF support for NE comparators.
992 * Revision 1.37 2000/11/29 01:34:17 steve
993 * Typo writing I pins to AND gates in compare.
995 * Revision 1.36 2000/11/22 21:18:20 steve
996 * Connect the CE if it is linked at all.
998 * Revision 1.35 2000/08/14 04:39:57 steve
999 * add th t-dll functions for net_const, net_bufz and processes.
1001 * Revision 1.34 2000/08/09 03:43:45 steve
1002 * Move all file manipulation out of target class.
1004 * Revision 1.33 2000/08/08 01:50:42 steve
1005 * target methods need not take a file stream.
1007 * Revision 1.32 2000/07/14 06:12:58 steve
1008 * Move inital value handling from NetNet to Nexus
1009 * objects. This allows better propogation of inital
1010 * values.
1012 * Clean up constant propagation a bit to account
1013 * for regs that are not really values.
1015 * Revision 1.31 2000/06/28 18:38:54 steve
1016 * Use nexus type to get nexus name.
1018 * Revision 1.30 2000/06/25 19:59:42 steve
1019 * Redesign Links to include the Nexus class that
1020 * carries properties of the connected set of links.
1022 * Revision 1.29 2000/05/14 17:55:04 steve
1023 * Support initialization of FF Q value.
1025 * Revision 1.28 2000/05/08 05:29:43 steve
1026 * no need for nobufz functor.
1028 * Revision 1.27 2000/05/07 04:37:56 steve
1029 * Carry strength values from Verilog source to the
1030 * pform and netlist for gates.
1032 * Change vvm constants to use the driver_t to drive
1033 * a constant value. This works better if there are
1034 * multiple drivers on a signal.
1036 * Revision 1.26 2000/04/23 23:03:13 steve
1037 * automatically generate macro interface code.
1039 * Revision 1.25 2000/04/23 21:15:07 steve
1040 * Emit code for the bufif devices.
1042 * Revision 1.24 2000/04/20 02:34:47 steve
1043 * Generate code for identity compare. Use gates.
1045 * Revision 1.23 2000/02/23 02:56:55 steve
1046 * Macintosh compilers do not support ident.
1048 * Revision 1.22 1999/12/17 03:38:46 steve
1049 * NetConst can now hold wide constants.
1051 * Revision 1.21 1999/12/16 18:54:32 steve
1052 * Capture the carry out of carry-chain addition.
1054 * Revision 1.20 1999/12/16 02:42:15 steve
1055 * Simulate carry output on adders.
1057 * Revision 1.19 1999/12/05 19:30:43 steve
1058 * Generate XNF RAMS from synthesized memories.
1060 * Revision 1.18 1999/11/19 03:02:25 steve
1061 * Detect flip-flops connected to opads and turn
1062 * them into OUTFF devices. Inprove support for
1063 * the XNF-LCA attribute in the process.
1065 * Revision 1.17 1999/11/17 18:52:09 steve
1066 * Add algorithm for choosing nexus name from attached signals.
1068 * Revision 1.16 1999/11/17 01:31:28 steve
1069 * Clean up warnings that add_sub got from Alliance
1071 * Revision 1.15 1999/11/06 04:51:42 steve
1072 * Support writing some XNF things into an NCF file.
1074 * Revision 1.14 1999/11/05 18:43:12 steve
1075 * fix syntax of EQN record.
1077 * Revision 1.13 1999/11/05 07:10:45 steve
1078 * Include the obvious XOR gates in the adders.
1080 * Revision 1.12 1999/11/05 04:40:40 steve
1081 * Patch to synthesize LPM_ADD_SUB from expressions,
1082 * Thanks to Larry Doolittle. Also handle constants
1083 * in expressions.
1085 * Synthesize adders in XNF, based on a patch from
1086 * Larry. Accept synthesis of constants from Larry
1087 * as is.
1089 * Revision 1.11 1999/11/04 03:53:26 steve
1090 * Patch to synthesize unary ~ and the ternary operator.
1091 * Thanks to Larry Doolittle <LRDoolittle@lbl.gov>.
1093 * Add the LPM_MUX device, and integrate it with the
1094 * ternary synthesis from Larry. Replace the lpm_mux
1095 * generator in t-xnf.cc to use XNF EQU devices to
1096 * put muxs into function units.
1098 * Rewrite elaborate_net for the PETernary class to
1099 * also use the LPM_MUX device.
1101 * Revision 1.10 1999/11/02 04:55:34 steve
1102 * Add the synthesize method to NetExpr to handle
1103 * synthesis of expressions, and use that method
1104 * to improve r-value handling of LPM_FF synthesis.
1106 * Modify the XNF target to handle LPM_FF objects.
1108 * Revision 1.9 1999/08/25 22:22:08 steve
1109 * handle bufz in XNF backend.
1111 * Revision 1.8 1999/08/18 04:00:02 steve
1112 * Fixup spelling and some error messages. <LRDoolittle@lbl.gov>
1114 * Revision 1.7 1999/07/17 03:39:11 steve
1115 * simplified process scan for targets.
1117 * Revision 1.6 1998/12/09 02:43:19 steve
1118 * Fix 2pin logic gates.
1120 * Revision 1.5 1998/12/07 04:53:17 steve
1121 * Generate OBUF or IBUF attributes (and the gates
1122 * to garry them) where a wire is a pad. This involved
1123 * figuring out enough of the netlist to know when such
1124 * was needed, and to generate new gates and signales
1125 * to handle what's missing.
1127 * Revision 1.4 1998/12/02 04:37:13 steve
1128 * Add the nobufz function to eliminate bufz objects,
1129 * Object links are marked with direction,
1130 * constant propagation is more careful will wide links,
1131 * Signal folding is aware of attributes, and
1132 * the XNF target can dump UDP objects based on LCA
1133 * attributes.
1135 * Revision 1.3 1998/11/23 00:20:24 steve
1136 * NetAssign handles lvalues as pin links
1137 * instead of a signal pointer,
1138 * Wire attributes added,
1139 * Ability to parse UDP descriptions added,
1140 * XNF generates EXT records for signals with
1141 * the PAD attribute.
1143 * Revision 1.2 1998/11/18 04:25:22 steve
1144 * Add -f flags for generic flag key/values.
1146 * Revision 1.1 1998/11/16 05:03:53 steve
1147 * Add the sigfold function that unlinks excess
1148 * signal nodes, and add the XNF target.