Merge branch 'master' into verilog-ams
[sverilog.git] / tgt-fpga / d-lpm.c
blob5e1891aacab239742436ee28c6bcd4704957ba5b
1 /*
2 * Copyright (c) 2003 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: d-lpm.c,v 1.12 2004/10/04 01:10:56 steve Exp $"
21 #endif
24 * This is the driver for a purely generic LPM module writer. This
25 * uses LPM version 2 1 0 devices, without particularly considering
26 * the target technology.
28 * The LPM standard is EIA-IS/103-A October 1996
29 * The output is EDIF 2 0 0 format.
32 # include "device.h"
33 # include "fpga_priv.h"
34 # include "edif.h"
35 # include "generic.h"
36 # include <string.h>
37 # include <assert.h>
39 static edif_cell_t lpm_cell_buf(void)
41 static edif_cell_t tmp = 0;
43 if (tmp != 0)
44 return tmp;
46 tmp = edif_xcell_create(xlib, "BUF", 2);
47 edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
48 edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
50 /* A buffer is an inverted inverter. */
51 edif_cell_port_pstring(tmp, 0, "LPM_Polarity", "INVERT");
53 edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
54 edif_cell_pinteger(tmp, "LPM_Width", 1);
55 edif_cell_pinteger(tmp, "LPM_Size", 1);
56 return tmp;
59 static edif_cell_t lpm_cell_inv(void)
61 static edif_cell_t tmp = 0;
63 if (tmp != 0)
64 return tmp;
66 tmp = edif_xcell_create(xlib, "INV", 2);
67 edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
68 edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
70 edif_cell_pstring(tmp, "LPM_TYPE", "LPM_INV");
71 edif_cell_pinteger(tmp, "LPM_Width", 1);
72 edif_cell_pinteger(tmp, "LPM_Size", 1);
73 return tmp;
76 static edif_cell_t lpm_cell_bufif0(void)
78 static edif_cell_t tmp = 0;
80 if (tmp != 0)
81 return tmp;
83 tmp = edif_xcell_create(xlib, "BUFIF1", 3);
84 edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
85 edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
86 edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
88 edif_cell_port_pstring(tmp, 2, "LPM_Polarity", "INVERT");
90 edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
91 edif_cell_pinteger(tmp, "LPM_Width", 1);
92 return tmp;
95 static edif_cell_t lpm_cell_bufif1(void)
97 static edif_cell_t tmp = 0;
99 if (tmp != 0)
100 return tmp;
102 tmp = edif_xcell_create(xlib, "BUFIF1", 3);
103 edif_cell_portconfig(tmp, 0, "TriData", IVL_SIP_OUTPUT);
104 edif_cell_portconfig(tmp, 1, "Data", IVL_SIP_INPUT);
105 edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
107 edif_cell_pstring(tmp, "LPM_TYPE", "LPM_BUSTRI");
108 edif_cell_pinteger(tmp, "LPM_Width", 1);
109 return tmp;
112 static edif_cell_t lpm_cell_or(unsigned siz)
114 unsigned idx;
115 edif_cell_t cell;
116 char name[32];
118 sprintf(name, "or%u", siz);
120 cell = edif_xlibrary_findcell(xlib, name);
121 if (cell != 0)
122 return cell;
124 cell = edif_xcell_create(xlib, strdup(name), siz+1);
126 edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
128 for (idx = 0 ; idx < siz ; idx += 1) {
129 sprintf(name, "Data%ux0", idx);
130 edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
133 edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
134 edif_cell_pinteger(cell, "LPM_Width", 1);
135 edif_cell_pinteger(cell, "LPM_Size", siz);
137 return cell;
140 static edif_cell_t lpm_cell_and(unsigned siz)
142 unsigned idx;
143 edif_cell_t cell;
144 char name[32];
146 sprintf(name, "and%u", siz);
148 cell = edif_xlibrary_findcell(xlib, name);
149 if (cell != 0)
150 return cell;
152 cell = edif_xcell_create(xlib, strdup(name), siz+1);
154 edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
156 for (idx = 0 ; idx < siz ; idx += 1) {
157 sprintf(name, "Data%ux0", idx);
158 edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
161 edif_cell_pstring(cell, "LPM_TYPE", "LPM_AND");
162 edif_cell_pinteger(cell, "LPM_Width", 1);
163 edif_cell_pinteger(cell, "LPM_Size", siz);
165 return cell;
168 static edif_cell_t lpm_cell_xor(unsigned siz)
170 unsigned idx;
171 edif_cell_t cell;
172 char name[32];
174 sprintf(name, "xor%u", siz);
176 cell = edif_xlibrary_findcell(xlib, name);
177 if (cell != 0)
178 return cell;
180 cell = edif_xcell_create(xlib, strdup(name), siz+1);
182 edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
184 for (idx = 0 ; idx < siz ; idx += 1) {
185 sprintf(name, "Data%ux0", idx);
186 edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
189 edif_cell_pstring(cell, "LPM_TYPE", "LPM_XOR");
190 edif_cell_pinteger(cell, "LPM_Width", 1);
191 edif_cell_pinteger(cell, "LPM_Size", siz);
193 return cell;
196 static edif_cell_t lpm_cell_nor(unsigned siz)
198 unsigned idx;
199 edif_cell_t cell;
200 char name[32];
202 sprintf(name, "nor%u", siz);
204 cell = edif_xlibrary_findcell(xlib, name);
205 if (cell != 0)
206 return cell;
208 cell = edif_xcell_create(xlib, strdup(name), siz+1);
210 edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
211 edif_cell_port_pstring(cell, 0, "LPM_Polarity", "INVERT");
213 for (idx = 0 ; idx < siz ; idx += 1) {
214 sprintf(name, "Data%ux0", idx);
215 edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
218 edif_cell_pstring(cell, "LPM_TYPE", "LPM_OR");
219 edif_cell_pinteger(cell, "LPM_Width", 1);
220 edif_cell_pinteger(cell, "LPM_Size", siz);
222 return cell;
225 static void lpm_show_header(ivl_design_t des)
227 unsigned idx;
228 ivl_scope_t root = ivl_design_root(des);
229 unsigned sig_cnt = ivl_scope_sigs(root);
230 unsigned nports = 0, pidx;
232 /* Count the ports I'm going to use. */
233 for (idx = 0 ; idx < sig_cnt ; idx += 1) {
234 ivl_signal_t sig = ivl_scope_sig(root, idx);
236 if (ivl_signal_port(sig) == IVL_SIP_NONE)
237 continue;
239 if (ivl_signal_attr(sig, "PAD") != 0)
240 continue;
242 nports += ivl_signal_pins(sig);
245 /* Create the base edf object. */
246 edf = edif_create(ivl_scope_basename(root), nports);
249 pidx = 0;
250 for (idx = 0 ; idx < sig_cnt ; idx += 1) {
251 edif_joint_t jnt;
252 ivl_signal_t sig = ivl_scope_sig(root, idx);
254 if (ivl_signal_port(sig) == IVL_SIP_NONE)
255 continue;
257 if (ivl_signal_attr(sig, "PAD") != 0)
258 continue;
260 if (ivl_signal_pins(sig) == 1) {
261 edif_portconfig(edf, pidx, ivl_signal_basename(sig),
262 ivl_signal_port(sig));
264 assert(ivl_signal_pins(sig) == 1);
265 jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
266 edif_port_to_joint(jnt, edf, pidx);
268 } else {
269 const char*name = ivl_signal_basename(sig);
270 ivl_signal_port_t dir = ivl_signal_port(sig);
271 char buf[128];
272 unsigned bit;
273 for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) {
274 const char*tmp;
275 sprintf(buf, "%s[%u]", name, bit);
276 tmp = strdup(buf);
277 edif_portconfig(edf, pidx+bit, tmp, dir);
279 jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
280 edif_port_to_joint(jnt, edf, pidx+bit);
284 pidx += ivl_signal_pins(sig);
287 assert(pidx == nports);
289 xlib = edif_xlibrary_create(edf, "LPM_LIBRARY");
292 static void lpm_show_footer(ivl_design_t des)
294 edif_print(xnf, edf);
297 static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell)
299 unsigned pin, idx;
301 edif_joint_t jnt;
302 edif_cellref_t ref = edif_cellref_create(edf, cell);
304 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
305 pin = edif_cell_port_byname(cell, "Result0");
306 edif_add_to_joint(jnt, ref, pin);
308 for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) {
309 char name[32];
311 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
312 sprintf(name, "Data%ux0", idx-1);
313 pin = edif_cell_port_byname(cell, name);
314 edif_add_to_joint(jnt, ref, pin);
318 static void lpm_logic(ivl_net_logic_t net)
320 edif_cell_t cell;
321 edif_cellref_t ref;
322 edif_joint_t jnt;
324 switch (ivl_logic_type(net)) {
326 case IVL_LO_BUFZ:
327 case IVL_LO_BUF:
328 assert(ivl_logic_pins(net) == 2);
329 cell = lpm_cell_buf();
330 ref = edif_cellref_create(edf, cell);
332 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
333 edif_add_to_joint(jnt, ref, 0);
335 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
336 edif_add_to_joint(jnt, ref, 1);
337 break;
339 case IVL_LO_BUFIF0:
340 assert(ivl_logic_pins(net) == 3);
341 cell = lpm_cell_bufif0();
342 ref = edif_cellref_create(edf, cell);
344 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
345 edif_add_to_joint(jnt, ref, 0);
347 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
348 edif_add_to_joint(jnt, ref, 1);
350 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
351 edif_add_to_joint(jnt, ref, 2);
352 break;
354 case IVL_LO_BUFIF1:
355 assert(ivl_logic_pins(net) == 3);
356 cell = lpm_cell_bufif1();
357 ref = edif_cellref_create(edf, cell);
359 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
360 edif_add_to_joint(jnt, ref, 0);
362 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
363 edif_add_to_joint(jnt, ref, 1);
365 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
366 edif_add_to_joint(jnt, ref, 2);
367 break;
369 case IVL_LO_NOT:
370 assert(ivl_logic_pins(net) == 2);
371 cell = lpm_cell_inv();
372 ref = edif_cellref_create(edf, cell);
374 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
375 edif_add_to_joint(jnt, ref, 0);
377 jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
378 edif_add_to_joint(jnt, ref, 1);
379 break;
381 case IVL_LO_OR:
382 cell = lpm_cell_or(ivl_logic_pins(net)-1);
383 hookup_logic_gate(net, cell);
384 break;
386 case IVL_LO_NOR:
387 cell = lpm_cell_nor(ivl_logic_pins(net)-1);
388 hookup_logic_gate(net, cell);
389 break;
391 case IVL_LO_AND:
392 cell = lpm_cell_and(ivl_logic_pins(net)-1);
393 hookup_logic_gate( net, cell);
394 break;
396 case IVL_LO_XOR:
397 cell = lpm_cell_xor(ivl_logic_pins(net)-1);
398 hookup_logic_gate( net, cell);
399 break;
401 default:
402 fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n",
403 ivl_logic_type(net));
404 break;
409 static void lpm_show_dff(ivl_lpm_t net)
411 char name[64];
412 edif_cell_t cell;
413 edif_cellref_t ref;
414 edif_joint_t jnt;
416 unsigned idx;
417 unsigned pin, wid = ivl_lpm_width(net);
419 sprintf(name, "fd%s%s%s%s%s%u",
420 ivl_lpm_enable(net)? "ce" : "",
421 ivl_lpm_async_clr(net)? "cl" : "",
422 ivl_lpm_sync_clr(net)? "sc" : "",
423 ivl_lpm_async_set(net)? "se" : "",
424 ivl_lpm_sync_set(net)? "ss" : "",
425 wid);
427 cell = edif_xlibrary_findcell(xlib, name);
429 if (cell == 0) {
430 unsigned nports = 2 * wid + 1;
431 pin = 0;
432 if (ivl_lpm_enable(net))
433 nports += 1;
434 if (ivl_lpm_async_clr(net))
435 nports += 1;
436 if (ivl_lpm_sync_clr(net))
437 nports += 1;
438 if (ivl_lpm_async_set(net))
439 nports += 1;
440 if (ivl_lpm_sync_set(net))
441 nports += 1;
443 cell = edif_xcell_create(xlib, strdup(name), nports);
444 edif_cell_pstring(cell, "LPM_Type", "LPM_FF");
445 edif_cell_pinteger(cell, "LPM_Width", wid);
447 for (idx = 0 ; idx < wid ; idx += 1) {
449 sprintf(name, "Q%u", idx);
450 edif_cell_portconfig(cell, idx*2+0, strdup(name),
451 IVL_SIP_OUTPUT);
453 sprintf(name, "Data%u", idx);
454 edif_cell_portconfig(cell, idx*2+1, strdup(name),
455 IVL_SIP_INPUT);
458 pin = wid*2;
460 if (ivl_lpm_enable(net)) {
461 edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT);
462 pin += 1;
465 if (ivl_lpm_async_clr(net)) {
466 edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT);
467 pin += 1;
470 if (ivl_lpm_sync_clr(net)) {
471 edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT);
472 pin += 1;
475 if (ivl_lpm_async_set(net)) {
476 edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT);
477 pin += 1;
480 if (ivl_lpm_sync_set(net)) {
481 edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT);
482 pin += 1;
485 edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT);
486 pin += 1;
488 assert(pin == nports);
491 ref = edif_cellref_create(edf, cell);
493 pin = edif_cell_port_byname(cell, "Clock");
495 jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
496 edif_add_to_joint(jnt, ref, pin);
498 if (ivl_lpm_enable(net)) {
499 pin = edif_cell_port_byname(cell, "Enable");
501 jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net));
502 edif_add_to_joint(jnt, ref, pin);
505 if (ivl_lpm_async_clr(net)) {
506 pin = edif_cell_port_byname(cell, "Aclr");
508 jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net));
509 edif_add_to_joint(jnt, ref, pin);
512 if (ivl_lpm_sync_clr(net)) {
513 pin = edif_cell_port_byname(cell, "Sclr");
515 jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net));
516 edif_add_to_joint(jnt, ref, pin);
519 if (ivl_lpm_async_set(net)) {
520 pin = edif_cell_port_byname(cell, "Aset");
522 jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net));
523 edif_add_to_joint(jnt, ref, pin);
526 if (ivl_lpm_sync_set(net)) {
527 ivl_expr_t svalue = ivl_lpm_sset_value(net);
529 pin = edif_cell_port_byname(cell, "Sset");
531 jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net));
532 edif_add_to_joint(jnt, ref, pin);
534 edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue));
537 for (idx = 0 ; idx < wid ; idx += 1) {
539 sprintf(name, "Q%u", idx);
540 pin = edif_cell_port_byname(cell, name);
542 jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
543 edif_add_to_joint(jnt, ref, pin);
545 sprintf(name, "Data%u", idx);
546 pin = edif_cell_port_byname(cell, name);
548 jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
549 edif_add_to_joint(jnt, ref, pin);
553 static void lpm_show_mux(ivl_lpm_t net)
555 edif_cell_t cell;
556 edif_cellref_t ref;
557 edif_joint_t jnt;
559 unsigned idx, rdx;
561 char cellname[32];
563 unsigned wid_r = ivl_lpm_width(net);
564 unsigned wid_s = ivl_lpm_selects(net);
565 unsigned wid_z = ivl_lpm_size(net);
567 sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z);
568 cell = edif_xlibrary_findcell(xlib, cellname);
570 if (cell == 0) {
571 unsigned pins = wid_r + wid_s + wid_r*wid_z;
573 cell = edif_xcell_create(xlib, strdup(cellname), pins);
575 /* Make the output ports. */
576 for (idx = 0 ; idx < wid_r ; idx += 1) {
577 sprintf(cellname, "Result%u", idx);
578 edif_cell_portconfig(cell, idx, strdup(cellname),
579 IVL_SIP_OUTPUT);
582 /* Make the select ports. */
583 for (idx = 0 ; idx < wid_s ; idx += 1) {
584 sprintf(cellname, "Sel%u", idx);
585 edif_cell_portconfig(cell, wid_r+idx, strdup(cellname),
586 IVL_SIP_INPUT);
589 for (idx = 0 ; idx < wid_z ; idx += 1) {
590 unsigned base = wid_r + wid_s + wid_r * idx;
591 unsigned rdx;
593 for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
594 sprintf(cellname, "Data%ux%u", idx, rdx);
595 edif_cell_portconfig(cell, base+rdx, strdup(cellname),
596 IVL_SIP_INPUT);
600 edif_cell_pstring(cell, "LPM_Type", "LPM_MUX");
601 edif_cell_pinteger(cell, "LPM_Width", wid_r);
602 edif_cell_pinteger(cell, "LPM_WidthS", wid_s);
603 edif_cell_pinteger(cell, "LPM_Size", wid_z);
607 ref = edif_cellref_create(edf, cell);
609 /* Connect the pins of the instance to the nexa. Access the
610 cell pins by name. */
611 for (idx = 0 ; idx < wid_r ; idx += 1) {
612 unsigned pin;
614 sprintf(cellname, "Result%u", idx);
615 pin = edif_cell_port_byname(cell, cellname);
617 jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
618 edif_add_to_joint(jnt, ref, pin);
621 for (idx = 0 ; idx < wid_s ; idx += 1) {
622 unsigned pin;
624 sprintf(cellname, "Sel%u", idx);
625 pin = edif_cell_port_byname(cell, cellname);
627 jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx));
628 edif_add_to_joint(jnt, ref, pin);
631 for (idx = 0 ; idx < wid_z ; idx += 1) {
632 for (rdx = 0 ; rdx < wid_r ; rdx += 1) {
633 unsigned pin;
635 sprintf(cellname, "Data%ux%u", idx, rdx);
636 pin = edif_cell_port_byname(cell, cellname);
638 jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx));
639 edif_add_to_joint(jnt, ref, pin);
644 static void lpm_show_add(ivl_lpm_t net)
646 unsigned idx;
647 unsigned cell_width;
648 char cellname[32];
649 edif_cell_t cell;
650 edif_cellref_t ref;
651 edif_joint_t jnt;
653 const char*type = "ADD";
655 if (ivl_lpm_type(net) == IVL_LPM_SUB)
656 type = "SUB";
658 /* Figure out the width of the cell. Normally, it is the LPM
659 width known by IVL. But if the top data input bits are
660 unconnected, then we really have a width one less, and we
661 can use the cout to fill out the output width. */
662 cell_width = ivl_lpm_width(net);
663 if ( (ivl_lpm_data(net,cell_width-1) == 0)
664 && (ivl_lpm_datab(net,cell_width-1) == 0) )
665 cell_width -= 1;
667 /* Find the correct ADD/SUB device in the library, search by
668 name. If the device is not there, then create it and put it
669 in the library. */
670 sprintf(cellname, "%s%u", type, cell_width);
671 cell = edif_xlibrary_findcell(xlib, cellname);
673 if (cell == 0) {
674 unsigned pins = cell_width * 3 + 1;
676 cell = edif_xcell_create(xlib, strdup(cellname), pins);
678 for (idx = 0 ; idx < cell_width ; idx += 1) {
680 sprintf(cellname, "Result%u", idx);
681 edif_cell_portconfig(cell, idx*3+0, strdup(cellname),
682 IVL_SIP_OUTPUT);
684 sprintf(cellname, "DataA%u", idx);
685 edif_cell_portconfig(cell, idx*3+1, strdup(cellname),
686 IVL_SIP_INPUT);
688 sprintf(cellname, "DataB%u", idx);
689 edif_cell_portconfig(cell, idx*3+2, strdup(cellname),
690 IVL_SIP_INPUT);
693 edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT);
695 edif_cell_pstring(cell, "LPM_Type", "LPM_ADD_SUB");
696 edif_cell_pstring(cell, "LPM_Direction", type);
697 edif_cell_pinteger(cell, "LPM_Width", ivl_lpm_width(net));
700 ref = edif_cellref_create(edf, cell);
702 /* Connect the pins of the instance to the nexa. Access the
703 cell pins by name. */
704 for (idx = 0 ; idx < cell_width ; idx += 1) {
705 unsigned pin;
707 sprintf(cellname, "Result%u", idx);
708 pin = edif_cell_port_byname(cell, cellname);
710 jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
711 edif_add_to_joint(jnt, ref, pin);
713 sprintf(cellname, "DataA%u", idx);
714 pin = edif_cell_port_byname(cell, cellname);
716 jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
717 edif_add_to_joint(jnt, ref, pin);
719 sprintf(cellname, "DataB%u", idx);
720 pin = edif_cell_port_byname(cell, cellname);
722 jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
723 edif_add_to_joint(jnt, ref, pin);
726 if (cell_width < ivl_lpm_width(net)) {
727 unsigned pin = edif_cell_port_byname(cell, "Cout");
729 jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width));
730 edif_add_to_joint(jnt, ref, pin);
734 static void lpm_show_mult(ivl_lpm_t net)
736 char name[64];
737 unsigned idx;
739 edif_cell_t cell;
740 edif_cellref_t ref;
741 edif_joint_t jnt;
743 sprintf(name, "mult%u", ivl_lpm_width(net));
744 cell = edif_xlibrary_findcell(xlib, name);
746 if (cell == 0) {
747 cell = edif_xcell_create(xlib, strdup(name),
748 3 * ivl_lpm_width(net));
750 for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
752 sprintf(name, "Result%u", idx);
753 edif_cell_portconfig(cell, idx*3+0,
754 strdup(name),
755 IVL_SIP_OUTPUT);
757 sprintf(name, "DataA%u", idx);
758 edif_cell_portconfig(cell, idx*3+1,
759 strdup(name),
760 IVL_SIP_INPUT);
762 sprintf(name, "DataB%u", idx);
763 edif_cell_portconfig(cell, idx*3+2,
764 strdup(name),
765 IVL_SIP_INPUT);
768 edif_cell_pstring(cell, "LPM_Type", "LPM_MULT");
769 edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net));
770 edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net));
771 edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net));
774 ref = edif_cellref_create(edf, cell);
776 for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) {
777 unsigned pin;
778 ivl_nexus_t nex;
780 sprintf(name, "Result%u", idx);
781 pin = edif_cell_port_byname(cell, name);
783 jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
784 edif_add_to_joint(jnt, ref, pin);
786 if ( (nex = ivl_lpm_data(net, idx)) ) {
787 sprintf(name, "DataA%u", idx);
788 pin = edif_cell_port_byname(cell, name);
790 jnt = edif_joint_of_nexus(edf, nex);
791 edif_add_to_joint(jnt, ref, pin);
794 if ( (nex = ivl_lpm_datab(net, idx)) ) {
795 sprintf(name, "DataB%u", idx);
796 pin = edif_cell_port_byname(cell, name);
798 jnt = edif_joint_of_nexus(edf, nex);
799 edif_add_to_joint(jnt, ref, pin);
805 static void lpm_show_constant(ivl_net_const_t net)
807 edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
808 edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
809 edif_cellref_t ref0 = 0, ref1 = 0;
811 const char*bits;
812 unsigned idx;
814 if (cell0 == 0) {
815 cell0 = edif_xcell_create(xlib, "cell0", 1);
816 edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT);
818 edif_cell_pstring(cell0, "LPM_Type", "LPM_CONSTANT");
819 edif_cell_pinteger(cell0, "LPM_Width", 1);
820 edif_cell_pinteger(cell0, "LPM_CValue", 0);
823 if (cell1 == 0) {
824 cell1 = edif_xcell_create(xlib, "cell1", 1);
825 edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT);
827 edif_cell_pstring(cell1, "LPM_Type", "LPM_CONSTANT");
828 edif_cell_pinteger(cell1, "LPM_Width", 1);
829 edif_cell_pinteger(cell1, "LPM_CValue", 1);
832 bits = ivl_const_bits(net);
833 for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
834 if (bits[idx] == '1') {
835 if (ref1 == 0)
836 ref1 = edif_cellref_create(edf, cell1);
838 } else {
839 if (ref0 == 0)
840 ref0 = edif_cellref_create(edf, cell0);
844 for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) {
845 edif_joint_t jnt;
847 jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx));
848 if (bits[idx] == '1')
849 edif_add_to_joint(jnt, ref1, 0);
850 else
851 edif_add_to_joint(jnt, ref0, 0);
857 const struct device_s d_lpm_edif = {
858 lpm_show_header,
859 lpm_show_footer,
862 lpm_logic,
863 lpm_show_dff, /* show_dff */
867 0, /* show_cmp_gt */
868 lpm_show_mux, /* show_mux */
869 lpm_show_add, /* show_add */
870 lpm_show_add, /* show_sub */
871 0, /* show_shiftl */
872 0, /* show_shiftr */
873 lpm_show_mult, /* show_mult */
874 lpm_show_constant /* show_constant */
878 * $Log: d-lpm.c,v $
879 * Revision 1.12 2004/10/04 01:10:56 steve
880 * Clean up spurious trailing white space.
882 * Revision 1.11 2003/11/12 03:20:14 steve
883 * devices need show_cmp_gt
885 * Revision 1.10 2003/10/31 03:45:50 steve
886 * Handle adders that use Cout for the top bit.
888 * Revision 1.9 2003/10/27 02:18:27 steve
889 * Emit constants for LPM device.
891 * Revision 1.8 2003/09/03 23:34:09 steve
892 * Support synchronous set of LPM_FF devices.
894 * Revision 1.7 2003/08/26 04:45:47 steve
895 * iverilog-vpi support --cflags a la gtk.
897 * Revision 1.6 2003/08/15 02:23:53 steve
898 * Add synthesis support for synchronous reset.
900 * Revision 1.5 2003/08/10 16:42:23 steve
901 * Add async clear to LPM_FF devices.
903 * Revision 1.4 2003/08/09 03:23:03 steve
904 * Add support for IVL_LPM_MULT device.
906 * Revision 1.3 2003/08/09 02:40:50 steve
907 * Generate LPM_FF devices.
909 * Revision 1.2 2003/08/07 05:18:04 steve
910 * Add support for OR/NOR/bufif0/bufif1.
912 * Revision 1.1 2003/08/07 04:04:01 steve
913 * Add an LPM device type.