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