1 /*
2  * Copyright (c) 2001-2014 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 # include  "device.h"
21 # include  "fpga_priv.h"
22 # include  <assert.h>
23 
24 /*
25  * This is the device emitter for the most generic FPGA. It doesn't
26  * know anything special about device types, so can't handle complex
27  * logic.
28  */
29 
xnf_draw_pin(ivl_nexus_t nex,const char * nam,char dir)30 static void xnf_draw_pin(ivl_nexus_t nex, const char*nam, char dir)
31 {
32       const char*use_name = nam;
33       const char*nex_name = xnf_mangle_nexus_name(nex);
34       int invert = 0;
35 
36       if (use_name[0] == '~') {
37 	    invert = 1;
38 	    use_name += 1;
39       }
40 
41       fprintf(xnf, "    PIN, %s, %c, %s", use_name, dir, nex_name);
42 
43       if (invert)
44 	    fprintf(xnf, ",,INV");
45 
46       fprintf(xnf, "\n");
47 }
48 
show_root_ports_xnf(ivl_scope_t root)49 static void show_root_ports_xnf(ivl_scope_t root)
50 {
51       unsigned cnt = ivl_scope_sigs(root);
52       unsigned idx;
53 
54       for (idx = 0 ;  idx < cnt ;  idx += 1) {
55 	    ivl_signal_t sig = ivl_scope_sig(root, idx);
56 	    const char*use_name;
57 
58 	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
59 		  continue;
60 
61 	    use_name = ivl_signal_basename(sig);
62 	    if (ivl_signal_pins(sig) == 1) {
63 		  ivl_nexus_t nex = ivl_signal_pin(sig, 0);
64 		  fprintf(xnf, "SIG, %s, PIN=%s\n",
65 			  xnf_mangle_nexus_name(nex), use_name);
66 
67 	    } else {
68 		  unsigned pin;
69 
70 		  for (pin = 0 ; pin < ivl_signal_pins(sig); pin += 1) {
71 			ivl_nexus_t nex = ivl_signal_pin(sig, pin);
72 			fprintf(xnf, "SIG, %s, PIN=%s%u\n",
73 				xnf_mangle_nexus_name(nex), use_name,
74 				pin);
75 		  }
76 	    }
77       }
78 }
79 
show_design_consts_xnf(ivl_design_t des)80 static void show_design_consts_xnf(ivl_design_t des)
81 {
82       unsigned idx;
83 
84       for (idx = 0 ;  idx < ivl_design_consts(des) ;  idx += 1) {
85 	    unsigned pin;
86 	    ivl_net_const_t net = ivl_design_const(des, idx);
87 	    const char*val = ivl_const_bits(net);
88 
89 	    for (pin = 0 ;  pin < ivl_const_pins(net) ;  pin += 1) {
90 		  ivl_nexus_t nex = ivl_const_pin(net, pin);
91 		  fprintf(xnf, "PWR,%c,%s\n", val[pin],
92 			  xnf_mangle_nexus_name(nex));
93 	    }
94       }
95 }
96 
generic_show_header(ivl_design_t des)97 static void generic_show_header(ivl_design_t des)
98 {
99       ivl_scope_t root = ivl_design_root(des);
100 
101       fprintf(xnf, "LCANET,6\n");
102       fprintf(xnf, "PROG,iverilog,$Name:  $,\"Icarus Verilog/fpga.tgt\"\n");
103 
104       if (part && (part[0]!=0)) {
105 	    fprintf(xnf, "PART,%s\n", part);
106       }
107 
108       show_root_ports_xnf(root);
109 }
110 
generic_show_footer(ivl_design_t des)111 static void generic_show_footer(ivl_design_t des)
112 {
113       show_design_consts_xnf(des);
114       fprintf(xnf, "EOF\n");
115 }
116 
117 
generic_show_logic(ivl_net_logic_t net)118 static void generic_show_logic(ivl_net_logic_t net)
119 {
120       char name[1024];
121       ivl_nexus_t nex;
122       unsigned idx;
123 
124       xnf_mangle_logic_name(net, name, sizeof name);
125 
126       switch (ivl_logic_type(net)) {
127 
128 	  case IVL_LO_AND:
129 	    fprintf(xnf, "SYM, %s, AND, LIBVER=2.0.0\n", name);
130 	    nex = ivl_logic_pin(net, 0);
131 	    xnf_draw_pin(nex, "O", 'O');
132 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
133 		  char ipin[32];
134 		  nex = ivl_logic_pin(net, idx);
135 		  sprintf(ipin, "I%u", idx-1);
136 		  xnf_draw_pin(nex, ipin, 'I');
137 	    }
138 	    fprintf(xnf, "END\n");
139 	    break;
140 
141 	  case IVL_LO_BUF:
142 	    assert(ivl_logic_pins(net) == 2);
143 	    fprintf(xnf, "SYM, %s, BUF, LIBVER=2.0.0\n", name);
144 	    nex = ivl_logic_pin(net, 0);
145 	    xnf_draw_pin(nex, "O", 'O');
146 	    nex = ivl_logic_pin(net, 1);
147 	    xnf_draw_pin(nex, "I", 'I');
148 	    fprintf(xnf, "END\n");
149 	    break;
150 
151 	  case IVL_LO_NAND:
152 	    fprintf(xnf, "SYM, %s, NAND, LIBVER=2.0.0\n", name);
153 	    nex = ivl_logic_pin(net, 0);
154 	    xnf_draw_pin(nex, "O", 'O');
155 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
156 		  char ipin[32];
157 		  nex = ivl_logic_pin(net, idx);
158 		  sprintf(ipin, "I%u", idx-1);
159 		  xnf_draw_pin(nex, ipin, 'I');
160 	    }
161 	    fprintf(xnf, "END\n");
162 	    break;
163 
164 	  case IVL_LO_NOR:
165 	    fprintf(xnf, "SYM, %s, NOR, LIBVER=2.0.0\n", name);
166 	    nex = ivl_logic_pin(net, 0);
167 	    xnf_draw_pin(nex, "O", 'O');
168 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
169 		  char ipin[32];
170 		  nex = ivl_logic_pin(net, idx);
171 		  sprintf(ipin, "I%u", idx-1);
172 		  xnf_draw_pin(nex, ipin, 'I');
173 	    }
174 	    fprintf(xnf, "END\n");
175 	    break;
176 
177 	  case IVL_LO_NOT:
178 	    assert(ivl_logic_pins(net) == 2);
179 	    fprintf(xnf, "SYM, %s, INV, LIBVER=2.0.0\n", name);
180 	    nex = ivl_logic_pin(net, 0);
181 	    xnf_draw_pin(nex, "O", 'O');
182 	    nex = ivl_logic_pin(net, 1);
183 	    xnf_draw_pin(nex, "I", 'I');
184 	    fprintf(xnf, "END\n");
185 	    break;
186 
187 	  case IVL_LO_OR:
188 	    fprintf(xnf, "SYM, %s, OR, LIBVER=2.0.0\n", name);
189 	    nex = ivl_logic_pin(net, 0);
190 	    xnf_draw_pin(nex, "O", 'O');
191 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
192 		  char ipin[32];
193 		  nex = ivl_logic_pin(net, idx);
194 		  sprintf(ipin, "I%u", idx-1);
195 		  xnf_draw_pin(nex, ipin, 'I');
196 	    }
197 	    fprintf(xnf, "END\n");
198 	    break;
199 
200 	  case IVL_LO_XOR:
201 	    fprintf(xnf, "SYM, %s, XOR, LIBVER=2.0.0\n", name);
202 	    nex = ivl_logic_pin(net, 0);
203 	    xnf_draw_pin(nex, "O", 'O');
204 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
205 		  char ipin[32];
206 		  nex = ivl_logic_pin(net, idx);
207 		  sprintf(ipin, "I%u", idx-1);
208 		  xnf_draw_pin(nex, ipin, 'I');
209 	    }
210 	    fprintf(xnf, "END\n");
211 	    break;
212 
213 	  case IVL_LO_XNOR:
214 	    fprintf(xnf, "SYM, %s, XNOR, LIBVER=2.0.0\n", name);
215 	    nex = ivl_logic_pin(net, 0);
216 	    xnf_draw_pin(nex, "O", 'O');
217 	    for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
218 		  char ipin[32];
219 		  nex = ivl_logic_pin(net, idx);
220 		  sprintf(ipin, "I%u", idx-1);
221 		  xnf_draw_pin(nex, ipin, 'I');
222 	    }
223 	    fprintf(xnf, "END\n");
224 	    break;
225 
226 	  case IVL_LO_BUFIF0:
227 	    fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name);
228 	    nex = ivl_logic_pin(net, 0);
229 	    xnf_draw_pin(nex, "O", 'O');
230 	    nex = ivl_logic_pin(net, 1);
231 	    xnf_draw_pin(nex, "I", 'I');
232 	    nex = ivl_logic_pin(net, 2);
233 	    xnf_draw_pin(nex, "~T", 'I');
234 	    fprintf(xnf, "END\n");
235 	    break;
236 
237 	  case IVL_LO_BUFIF1:
238 	    fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name);
239 	    nex = ivl_logic_pin(net, 0);
240 	    xnf_draw_pin(nex, "O", 'O');
241 	    nex = ivl_logic_pin(net, 1);
242 	    xnf_draw_pin(nex, "I", 'I');
243 	    nex = ivl_logic_pin(net, 2);
244 	    xnf_draw_pin(nex, "T", 'I');
245 	    fprintf(xnf, "END\n");
246 	    break;
247 
248 	  default:
249 	    fprintf(stderr, "fpga.tgt: unknown logic type %d\n",
250 		    ivl_logic_type(net));
251 	    break;
252       }
253 
254 }
255 
generic_show_dff(ivl_lpm_t net)256 static void generic_show_dff(ivl_lpm_t net)
257 {
258       char name[1024];
259       ivl_nexus_t nex;
260 
261       xnf_mangle_lpm_name(net, name, sizeof name);
262 
263       fprintf(xnf, "SYM, %s, DFF, LIBVER=2.0.0\n", name);
264 
265       nex = ivl_lpm_q(net, 0);
266       xnf_draw_pin(nex, "Q", 'O');
267 
268       nex = ivl_lpm_data(net, 0);
269       xnf_draw_pin(nex, "D", 'I');
270 
271       nex = ivl_lpm_clk(net);
272       xnf_draw_pin(nex, "C", 'I');
273 
274       if ((nex = ivl_lpm_enable(net)))
275 	    xnf_draw_pin(nex, "CE", 'I');
276 
277       fprintf(xnf, "END\n");
278 }
279 
280 /*
281  * The generic == comparator uses EQN records to generate 2-bit
282  * comparators, that are then connected together by a wide AND gate.
283  */
generic_show_cmp_eq(ivl_lpm_t net)284 static void generic_show_cmp_eq(ivl_lpm_t net)
285 {
286       ivl_nexus_t nex;
287       unsigned idx;
288       char name[1024];
289 	/* Make this many dual pair comparators, and */
290       unsigned deqn = ivl_lpm_width(net) / 2;
291 	/* Make this many single pair comparators. */
292       unsigned seqn = ivl_lpm_width(net) % 2;
293 
294       xnf_mangle_lpm_name(net, name, sizeof name);
295 
296       for (idx = 0 ;  idx < deqn ;  idx += 1) {
297 	    fprintf(xnf, "SYM, %s/CD%u, EQN, "
298 		    "EQN=(~((I0 @ I1) + (I2 @ I3)))\n",
299 		    name, idx);
300 
301 	    fprintf(xnf, "    PIN, O, O, %s/CDO%u\n", name, idx);
302 
303 	    nex = ivl_lpm_data(net, 2*idx);
304 	    xnf_draw_pin(nex, "I0", 'I');
305 	    nex = ivl_lpm_datab(net, 2*idx);
306 	    xnf_draw_pin(nex, "I1", 'I');
307 
308 	    nex = ivl_lpm_data(net, 2*idx+1);
309 	    xnf_draw_pin(nex, "I2", 'I');
310 	    nex = ivl_lpm_datab(net, 2*idx+1);
311 	    xnf_draw_pin(nex, "I3", 'I');
312 
313 	    fprintf(xnf, "END\n");
314       }
315 
316       if (seqn != 0) {
317 	    fprintf(xnf, "SYM, %s/CT, XNOR, LIBVER=2.0.0\n", name);
318 
319 	    fprintf(xnf, "    PIN, O, O, %s/CTO\n", name);
320 
321 	    nex = ivl_lpm_data(net, 2*deqn);
322 	    xnf_draw_pin(nex, "I0", 'I');
323 
324 	    nex = ivl_lpm_datab(net, 2*deqn);
325 	    xnf_draw_pin(nex, "I1", 'I');
326 
327 	    fprintf(xnf, "END\n");
328       }
329 
330       if (ivl_lpm_type(net) == IVL_LPM_CMP_EQ)
331 	    fprintf(xnf, "SYM, %s/OUT, AND, LIBVER=2.0.0\n", name);
332       else
333 	    fprintf(xnf, "SYM, %s/OUT, NAND, LIBVER=2.0.0\n", name);
334 
335       nex = ivl_lpm_q(net, 0);
336       xnf_draw_pin(nex, "O", 'O');
337 
338       for (idx = 0 ;  idx < deqn ;  idx += 1)
339 	    fprintf(xnf, "    PIN, I%u, I, %s/CDO%u\n", idx, name, idx);
340 
341       for (idx = 0 ;  idx < seqn ;  idx += 1)
342 	    fprintf(xnf, "    PIN, I%u, I, %s/CTO\n", deqn+idx, name);
343 
344       fprintf(xnf, "END\n");
345 }
346 
347 /*
348  * This function draws N-bit wide binary mux devices. These are so
349  * very popular because they are the result of such expressions as:
350  *
351  *        x = sel? a : b;
352  *
353  * This code only supports the case where sel is a single bit. It
354  * works by drawing for each bit of the width an EQN device that takes
355  * as inputs I0 and I1 the alternative inputs, and I2 the select. The
356  * select bit is common with all the generated mux devices.
357  */
generic_show_mux(ivl_lpm_t net)358 static void generic_show_mux(ivl_lpm_t net)
359 {
360       char name[1024];
361       ivl_nexus_t sel;
362       unsigned idx;
363 
364       xnf_mangle_lpm_name(net, name, sizeof name);
365 
366 	/* Access the single select bit. This is common to the whole
367 	   width of the mux. */
368       assert(ivl_lpm_selects(net) == 1);
369       sel = ivl_lpm_select(net, 0);
370 
371       for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
372 	    ivl_nexus_t nex;
373 
374 	    fprintf(xnf, "SYM, %s/M%u, EQN, "
375 		    "EQN=((I0 * ~I2) + (I1 * I2))\n",
376 		    name, idx);
377 
378 	    nex = ivl_lpm_q(net, idx);
379 	    xnf_draw_pin(nex, "O", 'O');
380 
381 	    nex = ivl_lpm_data2(net, 0, idx);
382 	    xnf_draw_pin(nex, "I0", 'I');
383 
384 	    nex = ivl_lpm_data2(net, 1, idx);
385 	    xnf_draw_pin(nex, "I1", 'I');
386 
387 	    xnf_draw_pin(sel, "I2", 'I');
388 
389 	    fprintf(xnf, "END\n");
390       }
391 }
392 
393 /*
394  * This code cheats and just generates ADD4 devices enough to support
395  * the add. Make no effort to optimize, because we have no idea what
396  * kind of device we have.
397  */
generic_show_add(ivl_lpm_t net)398 static void generic_show_add(ivl_lpm_t net)
399 {
400       char name[1024];
401       ivl_nexus_t nex;
402       unsigned idx, nadd4, tail;
403 
404       xnf_mangle_lpm_name(net, name, sizeof name);
405 
406 	/* Make this many ADD4 devices. */
407       nadd4 = ivl_lpm_width(net) / 4;
408       tail  = ivl_lpm_width(net) % 4;
409 
410       for (idx = 0 ;  idx < nadd4 ;  idx += 1) {
411 	    fprintf(xnf, "SYM, %s/A%u, ADD4\n", name, idx);
412 
413 	    if (idx > 0)
414 		  fprintf(xnf, "    PIN, CI, I, %s/CO%u\n", name, idx-1);
415 
416 	    nex = ivl_lpm_q(net, idx*4+0);
417 	    xnf_draw_pin(nex, "S0", 'O');
418 
419 	    nex = ivl_lpm_q(net, idx*4+1);
420 	    xnf_draw_pin(nex, "S1", 'O');
421 
422 	    nex = ivl_lpm_q(net, idx*4+2);
423 	    xnf_draw_pin(nex, "S2", 'O');
424 
425 	    nex = ivl_lpm_q(net, idx*4+3);
426 	    xnf_draw_pin(nex, "S3", 'O');
427 
428 	    nex = ivl_lpm_data(net, idx*4+0);
429 	    xnf_draw_pin(nex, "A0", 'I');
430 
431 	    nex = ivl_lpm_data(net, idx*4+1);
432 	    xnf_draw_pin(nex, "A1", 'I');
433 
434 	    nex = ivl_lpm_data(net, idx*4+2);
435 	    xnf_draw_pin(nex, "A2", 'I');
436 
437 	    nex = ivl_lpm_data(net, idx*4+3);
438 	    xnf_draw_pin(nex, "A3", 'I');
439 
440 	    nex = ivl_lpm_datab(net, idx*4+0);
441 	    xnf_draw_pin(nex, "B0", 'I');
442 
443 	    nex = ivl_lpm_datab(net, idx*4+1);
444 	    xnf_draw_pin(nex, "B1", 'I');
445 
446 	    nex = ivl_lpm_datab(net, idx*4+2);
447 	    xnf_draw_pin(nex, "B2", 'I');
448 
449 	    nex = ivl_lpm_datab(net, idx*4+3);
450 	    xnf_draw_pin(nex, "B3", 'I');
451 
452 	    if ((idx*4+4) < ivl_lpm_width(net))
453 		  fprintf(xnf, "    PIN, CO, O, %s/CO%u\n", name, idx);
454 
455 	    fprintf(xnf, "END\n");
456       }
457 
458       if (tail > 0) {
459 	    fprintf(xnf, "SYM, %s/A%u, ADD4\n", name, nadd4);
460 	    if (nadd4 > 0)
461 		  fprintf(xnf, "    PIN, CI, I, %s/CO%u\n", name, nadd4-1);
462 
463 	    switch (tail) {
464 		case 3:
465 		  nex = ivl_lpm_data(net, nadd4*4+2);
466 		  xnf_draw_pin(nex, "A2", 'I');
467 
468 		  nex = ivl_lpm_datab(net, nadd4*4+2);
469 		  xnf_draw_pin(nex, "B2", 'I');
470 
471 		  nex = ivl_lpm_q(net, nadd4*4+2);
472 		  xnf_draw_pin(nex, "S2", 'O');
473 		case 2:
474 		  nex = ivl_lpm_data(net, nadd4*4+1);
475 		  xnf_draw_pin(nex, "A1", 'I');
476 
477 		  nex = ivl_lpm_datab(net, nadd4*4+1);
478 		  xnf_draw_pin(nex, "B1", 'I');
479 
480 		  nex = ivl_lpm_q(net, nadd4*4+1);
481 		  xnf_draw_pin(nex, "S1", 'O');
482 		case 1:
483 		  nex = ivl_lpm_data(net, nadd4*4+0);
484 		  xnf_draw_pin(nex, "A0", 'I');
485 
486 		  nex = ivl_lpm_datab(net, nadd4*4+0);
487 		  xnf_draw_pin(nex, "B0", 'I');
488 
489 		  nex = ivl_lpm_q(net, nadd4*4+0);
490 		  xnf_draw_pin(nex, "S0", 'O');
491 	    }
492 
493 	    fprintf(xnf, "END\n");
494       }
495 }
496 
497 const struct device_s d_generic = {
498       generic_show_header,
499       generic_show_footer,
500       0, /* show_scope */
501       0, /* show_pad not implemented */
502       generic_show_logic,
503       generic_show_dff,
504       generic_show_cmp_eq,
505       generic_show_cmp_eq,
506       0, /* ge not implemented */
507       0, /* gt not implemented */
508       generic_show_mux,
509       generic_show_add,
510       0, /* subtract not implemented */
511       0,
512       0
513 };
514