1 /*
2  * Copyright (c) 2003-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 /*
21  * This is the driver for a purely generic LPM module writer. This
22  * uses LPM version 2 1 0 devices, without particularly considering
23  * the target technology.
24  *
25  * The LPM standard is EIA-IS/103-A  October 1996
26  * The output is EDIF 2 0 0 format.
27  */
28 
29 # include  "device.h"
30 # include  "fpga_priv.h"
31 # include  "edif.h"
32 # include  "generic.h"
33 # include  <string.h>
34 # include  <assert.h>
35 
lpm_cell_buf(void)36 static edif_cell_t lpm_cell_buf(void)
37 {
38       static edif_cell_t tmp = 0;
39 
40       if (tmp != 0)
41 	    return tmp;
42 
43       tmp = edif_xcell_create(xlib, "BUF", 2);
44       edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
45       edif_cell_portconfig(tmp, 1, "Data",   IVL_SIP_INPUT);
46 
47 	/* A buffer is an inverted inverter. */
48       edif_cell_port_pstring(tmp, 0, "LPM_Polarity", "INVERT");
49 
50       edif_cell_pstring(tmp,  "LPM_TYPE",  "LPM_INV");
51       edif_cell_pinteger(tmp, "LPM_Width", 1);
52       edif_cell_pinteger(tmp, "LPM_Size",  1);
53       return tmp;
54 }
55 
lpm_cell_inv(void)56 static edif_cell_t lpm_cell_inv(void)
57 {
58       static edif_cell_t tmp = 0;
59 
60       if (tmp != 0)
61 	    return tmp;
62 
63       tmp = edif_xcell_create(xlib, "INV", 2);
64       edif_cell_portconfig(tmp, 0, "Result", IVL_SIP_OUTPUT);
65       edif_cell_portconfig(tmp, 1, "Data",   IVL_SIP_INPUT);
66 
67       edif_cell_pstring(tmp,  "LPM_TYPE",  "LPM_INV");
68       edif_cell_pinteger(tmp, "LPM_Width", 1);
69       edif_cell_pinteger(tmp, "LPM_Size",  1);
70       return tmp;
71 }
72 
lpm_cell_bufif0(void)73 static edif_cell_t lpm_cell_bufif0(void)
74 {
75       static edif_cell_t tmp = 0;
76 
77       if (tmp != 0)
78 	    return tmp;
79 
80       tmp = edif_xcell_create(xlib, "BUFIF1", 3);
81       edif_cell_portconfig(tmp, 0, "TriData",  IVL_SIP_OUTPUT);
82       edif_cell_portconfig(tmp, 1, "Data",     IVL_SIP_INPUT);
83       edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
84 
85       edif_cell_port_pstring(tmp, 2, "LPM_Polarity", "INVERT");
86 
87       edif_cell_pstring(tmp,  "LPM_TYPE",  "LPM_BUSTRI");
88       edif_cell_pinteger(tmp, "LPM_Width", 1);
89       return tmp;
90 }
91 
lpm_cell_bufif1(void)92 static edif_cell_t lpm_cell_bufif1(void)
93 {
94       static edif_cell_t tmp = 0;
95 
96       if (tmp != 0)
97 	    return tmp;
98 
99       tmp = edif_xcell_create(xlib, "BUFIF1", 3);
100       edif_cell_portconfig(tmp, 0, "TriData",  IVL_SIP_OUTPUT);
101       edif_cell_portconfig(tmp, 1, "Data",     IVL_SIP_INPUT);
102       edif_cell_portconfig(tmp, 2, "EnableDT", IVL_SIP_INPUT);
103 
104       edif_cell_pstring(tmp,  "LPM_TYPE",  "LPM_BUSTRI");
105       edif_cell_pinteger(tmp, "LPM_Width", 1);
106       return tmp;
107 }
108 
lpm_cell_or(unsigned siz)109 static edif_cell_t lpm_cell_or(unsigned siz)
110 {
111       unsigned idx;
112       edif_cell_t cell;
113       char name[32];
114 
115       sprintf(name, "or%u", siz);
116 
117       cell = edif_xlibrary_findcell(xlib, name);
118       if (cell != 0)
119 	    return cell;
120 
121       cell = edif_xcell_create(xlib, strdup(name), siz+1);
122 
123       edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
124 
125       for (idx = 0 ;  idx < siz ;  idx += 1) {
126 	    sprintf(name, "Data%ux0", idx);
127 	    edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
128       }
129 
130       edif_cell_pstring(cell,  "LPM_TYPE",  "LPM_OR");
131       edif_cell_pinteger(cell, "LPM_Width", 1);
132       edif_cell_pinteger(cell, "LPM_Size",  siz);
133 
134       return cell;
135 }
136 
lpm_cell_and(unsigned siz)137 static edif_cell_t lpm_cell_and(unsigned siz)
138 {
139       unsigned idx;
140       edif_cell_t cell;
141       char name[32];
142 
143       sprintf(name, "and%u", siz);
144 
145       cell = edif_xlibrary_findcell(xlib, name);
146       if (cell != 0)
147 	    return cell;
148 
149       cell = edif_xcell_create(xlib, strdup(name), siz+1);
150 
151       edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
152 
153       for (idx = 0 ;  idx < siz ;  idx += 1) {
154 	    sprintf(name, "Data%ux0", idx);
155 	    edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
156       }
157 
158       edif_cell_pstring(cell,  "LPM_TYPE",  "LPM_AND");
159       edif_cell_pinteger(cell, "LPM_Width", 1);
160       edif_cell_pinteger(cell, "LPM_Size",  siz);
161 
162       return cell;
163 }
164 
lpm_cell_xor(unsigned siz)165 static edif_cell_t lpm_cell_xor(unsigned siz)
166 {
167       unsigned idx;
168       edif_cell_t cell;
169       char name[32];
170 
171       sprintf(name, "xor%u", siz);
172 
173       cell = edif_xlibrary_findcell(xlib, name);
174       if (cell != 0)
175 	    return cell;
176 
177       cell = edif_xcell_create(xlib, strdup(name), siz+1);
178 
179       edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
180 
181       for (idx = 0 ;  idx < siz ;  idx += 1) {
182 	    sprintf(name, "Data%ux0", idx);
183 	    edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
184       }
185 
186       edif_cell_pstring(cell,  "LPM_TYPE",  "LPM_XOR");
187       edif_cell_pinteger(cell, "LPM_Width", 1);
188       edif_cell_pinteger(cell, "LPM_Size",  siz);
189 
190       return cell;
191 }
192 
lpm_cell_nor(unsigned siz)193 static edif_cell_t lpm_cell_nor(unsigned siz)
194 {
195       unsigned idx;
196       edif_cell_t cell;
197       char name[32];
198 
199       sprintf(name, "nor%u", siz);
200 
201       cell = edif_xlibrary_findcell(xlib, name);
202       if (cell != 0)
203 	    return cell;
204 
205       cell = edif_xcell_create(xlib, strdup(name), siz+1);
206 
207       edif_cell_portconfig(cell, 0, "Result0", IVL_SIP_OUTPUT);
208       edif_cell_port_pstring(cell, 0, "LPM_Polarity", "INVERT");
209 
210       for (idx = 0 ;  idx < siz ;  idx += 1) {
211 	    sprintf(name, "Data%ux0", idx);
212 	    edif_cell_portconfig(cell, idx+1, strdup(name), IVL_SIP_INPUT);
213       }
214 
215       edif_cell_pstring(cell,  "LPM_TYPE",  "LPM_OR");
216       edif_cell_pinteger(cell, "LPM_Width", 1);
217       edif_cell_pinteger(cell, "LPM_Size",  siz);
218 
219       return cell;
220 }
221 
lpm_show_header(ivl_design_t des)222 static void lpm_show_header(ivl_design_t des)
223 {
224       unsigned idx;
225       ivl_scope_t root = ivl_design_root(des);
226       unsigned sig_cnt = ivl_scope_sigs(root);
227       unsigned nports = 0, pidx;
228 
229 	/* Count the ports I'm going to use. */
230       for (idx = 0 ;  idx < sig_cnt ;  idx += 1) {
231 	    ivl_signal_t sig = ivl_scope_sig(root, idx);
232 
233 	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
234 		  continue;
235 
236 	    if (ivl_signal_attr(sig, "PAD") != 0)
237 		  continue;
238 
239 	    nports += ivl_signal_pins(sig);
240       }
241 
242 	/* Create the base edf object. */
243       edf = edif_create(ivl_scope_basename(root), nports);
244 
245 
246       pidx = 0;
247       for (idx = 0 ;  idx < sig_cnt ;  idx += 1) {
248 	    edif_joint_t jnt;
249 	    ivl_signal_t sig = ivl_scope_sig(root, idx);
250 
251 	    if (ivl_signal_port(sig) == IVL_SIP_NONE)
252 		  continue;
253 
254 	    if (ivl_signal_attr(sig, "PAD") != 0)
255 		  continue;
256 
257 	    if (ivl_signal_pins(sig) == 1) {
258 		  edif_portconfig(edf, pidx, ivl_signal_basename(sig),
259 				  ivl_signal_port(sig));
260 
261 		  assert(ivl_signal_pins(sig) == 1);
262 		  jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0));
263 		  edif_port_to_joint(jnt, edf, pidx);
264 
265 	    } else {
266 		  const char*name = ivl_signal_basename(sig);
267 		  ivl_signal_port_t dir = ivl_signal_port(sig);
268 		  char buf[128];
269 		  unsigned bit;
270 		  for (bit = 0 ;  bit < ivl_signal_pins(sig) ; bit += 1) {
271 			const char*tmp;
272 			sprintf(buf, "%s[%u]", name, bit);
273 			tmp = strdup(buf);
274 			edif_portconfig(edf, pidx+bit, tmp, dir);
275 
276 			jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit));
277 			edif_port_to_joint(jnt, edf, pidx+bit);
278 		  }
279 	    }
280 
281 	    pidx += ivl_signal_pins(sig);
282       }
283 
284       assert(pidx == nports);
285 
286       xlib = edif_xlibrary_create(edf, "LPM_LIBRARY");
287 }
288 
lpm_show_footer(ivl_design_t des)289 static void lpm_show_footer(ivl_design_t des)
290 {
291       edif_print(xnf, edf);
292 }
293 
hookup_logic_gate(ivl_net_logic_t net,edif_cell_t cell)294 static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell)
295 {
296       unsigned pin, idx;
297 
298       edif_joint_t jnt;
299       edif_cellref_t ref = edif_cellref_create(edf, cell);
300 
301       jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
302       pin = edif_cell_port_byname(cell, "Result0");
303       edif_add_to_joint(jnt, ref, pin);
304 
305       for (idx = 1 ;  idx < ivl_logic_pins(net) ;  idx += 1) {
306 	    char name[32];
307 
308 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx));
309 	    sprintf(name, "Data%ux0", idx-1);
310 	    pin = edif_cell_port_byname(cell, name);
311 	    edif_add_to_joint(jnt, ref, pin);
312       }
313 }
314 
lpm_logic(ivl_net_logic_t net)315 static void lpm_logic(ivl_net_logic_t net)
316 {
317       edif_cell_t cell;
318       edif_cellref_t ref;
319       edif_joint_t jnt;
320 
321       switch (ivl_logic_type(net)) {
322 
323 	  case IVL_LO_BUFZ:
324 	  case IVL_LO_BUF:
325 	    assert(ivl_logic_pins(net) == 2);
326 	    cell = lpm_cell_buf();
327 	    ref = edif_cellref_create(edf, cell);
328 
329 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
330 	    edif_add_to_joint(jnt, ref, 0);
331 
332 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
333 	    edif_add_to_joint(jnt, ref, 1);
334 	    break;
335 
336 	  case IVL_LO_BUFIF0:
337 	    assert(ivl_logic_pins(net) == 3);
338 	    cell = lpm_cell_bufif0();
339 	    ref = edif_cellref_create(edf, cell);
340 
341 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
342 	    edif_add_to_joint(jnt, ref, 0);
343 
344 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
345 	    edif_add_to_joint(jnt, ref, 1);
346 
347 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
348 	    edif_add_to_joint(jnt, ref, 2);
349 	    break;
350 
351 	  case IVL_LO_BUFIF1:
352 	    assert(ivl_logic_pins(net) == 3);
353 	    cell = lpm_cell_bufif1();
354 	    ref = edif_cellref_create(edf, cell);
355 
356 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
357 	    edif_add_to_joint(jnt, ref, 0);
358 
359 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
360 	    edif_add_to_joint(jnt, ref, 1);
361 
362 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2));
363 	    edif_add_to_joint(jnt, ref, 2);
364 	    break;
365 
366 	  case IVL_LO_NOT:
367 	    assert(ivl_logic_pins(net) == 2);
368 	    cell = lpm_cell_inv();
369 	    ref = edif_cellref_create(edf, cell);
370 
371 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0));
372 	    edif_add_to_joint(jnt, ref, 0);
373 
374 	    jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1));
375 	    edif_add_to_joint(jnt, ref, 1);
376 	    break;
377 
378 	  case IVL_LO_OR:
379 	    cell = lpm_cell_or(ivl_logic_pins(net)-1);
380 	    hookup_logic_gate(net, cell);
381 	    break;
382 
383 	  case IVL_LO_NOR:
384 	    cell = lpm_cell_nor(ivl_logic_pins(net)-1);
385 	    hookup_logic_gate(net, cell);
386 	    break;
387 
388 	  case IVL_LO_AND:
389 	    cell = lpm_cell_and(ivl_logic_pins(net)-1);
390 	    hookup_logic_gate( net, cell);
391 	    break;
392 
393 	  case IVL_LO_XOR:
394 	    cell = lpm_cell_xor(ivl_logic_pins(net)-1);
395 	    hookup_logic_gate( net, cell);
396 	    break;
397 
398 	  default:
399 	    fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %d\n",
400 		    ivl_logic_type(net));
401 	    break;
402       }
403 }
404 
405 
lpm_show_dff(ivl_lpm_t net)406 static void lpm_show_dff(ivl_lpm_t net)
407 {
408       char name[64];
409       edif_cell_t cell;
410       edif_cellref_t ref;
411       edif_joint_t jnt;
412 
413       unsigned idx;
414       unsigned pin, wid = ivl_lpm_width(net);
415 
416       sprintf(name, "fd%s%s%s%s%s%u",
417 	      ivl_lpm_enable(net)? "ce" : "",
418 	      ivl_lpm_async_clr(net)? "cl" : "",
419 	      ivl_lpm_sync_clr(net)? "sc" : "",
420 	      ivl_lpm_async_set(net)? "se" : "",
421 	      ivl_lpm_sync_set(net)? "ss" : "",
422 	      wid);
423 
424       cell = edif_xlibrary_findcell(xlib, name);
425 
426       if (cell == 0) {
427 	    unsigned nports = 2 * wid + 1;
428 	    pin = 0;
429 	    if (ivl_lpm_enable(net))
430 		  nports += 1;
431 	    if (ivl_lpm_async_clr(net))
432 		  nports += 1;
433 	    if (ivl_lpm_sync_clr(net))
434 		  nports += 1;
435 	    if (ivl_lpm_async_set(net))
436 		  nports += 1;
437 	    if (ivl_lpm_sync_set(net))
438 		  nports += 1;
439 
440 	    cell = edif_xcell_create(xlib, strdup(name), nports);
441 	    edif_cell_pstring(cell,  "LPM_Type", "LPM_FF");
442 	    edif_cell_pinteger(cell, "LPM_Width", wid);
443 
444 	    for (idx = 0 ;  idx < wid ;  idx += 1) {
445 
446 		  sprintf(name, "Q%u", idx);
447 		  edif_cell_portconfig(cell, idx*2+0, strdup(name),
448 				       IVL_SIP_OUTPUT);
449 
450 		  sprintf(name, "Data%u", idx);
451 		  edif_cell_portconfig(cell, idx*2+1, strdup(name),
452 				       IVL_SIP_INPUT);
453 	    }
454 
455 	    pin = wid*2;
456 
457 	    if (ivl_lpm_enable(net)) {
458 		  edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT);
459 		  pin += 1;
460 	    }
461 
462 	    if (ivl_lpm_async_clr(net)) {
463 		  edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT);
464 		  pin += 1;
465 	    }
466 
467 	    if (ivl_lpm_sync_clr(net)) {
468 		  edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT);
469 		  pin += 1;
470 	    }
471 
472 	    if (ivl_lpm_async_set(net)) {
473 		  edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT);
474 		  pin += 1;
475 	    }
476 
477 	    if (ivl_lpm_sync_set(net)) {
478 		  edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT);
479 		  pin += 1;
480 	    }
481 
482 	    edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT);
483 	    pin += 1;
484 
485 	    assert(pin == nports);
486       }
487 
488       ref = edif_cellref_create(edf, cell);
489 
490       pin = edif_cell_port_byname(cell, "Clock");
491 
492       jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net));
493       edif_add_to_joint(jnt, ref, pin);
494 
495       if (ivl_lpm_enable(net)) {
496 	    pin = edif_cell_port_byname(cell, "Enable");
497 
498 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net));
499 	    edif_add_to_joint(jnt, ref, pin);
500       }
501 
502       if (ivl_lpm_async_clr(net)) {
503 	    pin = edif_cell_port_byname(cell, "Aclr");
504 
505 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net));
506 	    edif_add_to_joint(jnt, ref, pin);
507       }
508 
509       if (ivl_lpm_sync_clr(net)) {
510 	    pin = edif_cell_port_byname(cell, "Sclr");
511 
512 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net));
513 	    edif_add_to_joint(jnt, ref, pin);
514       }
515 
516       if (ivl_lpm_async_set(net)) {
517 	    pin = edif_cell_port_byname(cell, "Aset");
518 
519 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net));
520 	    edif_add_to_joint(jnt, ref, pin);
521       }
522 
523       if (ivl_lpm_sync_set(net)) {
524 	    ivl_expr_t svalue = ivl_lpm_sset_value(net);
525 
526 	    pin = edif_cell_port_byname(cell, "Sset");
527 
528 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net));
529 	    edif_add_to_joint(jnt, ref, pin);
530 
531 	    edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue));
532       }
533 
534       for (idx = 0 ;  idx < wid ;  idx += 1) {
535 
536 	    sprintf(name, "Q%u", idx);
537 	    pin = edif_cell_port_byname(cell, name);
538 
539 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
540 	    edif_add_to_joint(jnt, ref, pin);
541 
542 	    sprintf(name, "Data%u", idx);
543 	    pin = edif_cell_port_byname(cell, name);
544 
545 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
546 	    edif_add_to_joint(jnt, ref, pin);
547       }
548 }
549 
lpm_show_mux(ivl_lpm_t net)550 static void lpm_show_mux(ivl_lpm_t net)
551 {
552       edif_cell_t cell;
553       edif_cellref_t ref;
554       edif_joint_t jnt;
555 
556       unsigned idx, rdx;
557 
558       char cellname[32];
559 
560       unsigned wid_r = ivl_lpm_width(net);
561       unsigned wid_s = ivl_lpm_selects(net);
562       unsigned wid_z = ivl_lpm_size(net);
563 
564       sprintf(cellname, "mux%u_%u_%u", wid_r, wid_s, wid_z);
565       cell = edif_xlibrary_findcell(xlib, cellname);
566 
567       if (cell == 0) {
568 	    unsigned pins = wid_r + wid_s + wid_r*wid_z;
569 
570 	    cell = edif_xcell_create(xlib, strdup(cellname), pins);
571 
572 	      /* Make the output ports. */
573 	    for (idx = 0 ;  idx < wid_r ;  idx += 1) {
574 		  sprintf(cellname, "Result%u", idx);
575 		  edif_cell_portconfig(cell, idx, strdup(cellname),
576 				       IVL_SIP_OUTPUT);
577 	    }
578 
579 	      /* Make the select ports. */
580 	    for (idx = 0 ;  idx < wid_s ;  idx += 1) {
581 		  sprintf(cellname, "Sel%u", idx);
582 		  edif_cell_portconfig(cell, wid_r+idx, strdup(cellname),
583 				       IVL_SIP_INPUT);
584 	    }
585 
586 	    for (idx = 0 ;  idx < wid_z ; idx += 1) {
587 		  unsigned base = wid_r + wid_s + wid_r * idx;
588 		  unsigned rdx;
589 
590 		  for (rdx = 0 ;  rdx < wid_r ;  rdx += 1) {
591 			sprintf(cellname, "Data%ux%u", idx, rdx);
592 			edif_cell_portconfig(cell, base+rdx, strdup(cellname),
593 					     IVL_SIP_INPUT);
594 		  }
595 	    }
596 
597 	    edif_cell_pstring(cell,  "LPM_Type",   "LPM_MUX");
598 	    edif_cell_pinteger(cell, "LPM_Width",  wid_r);
599 	    edif_cell_pinteger(cell, "LPM_WidthS", wid_s);
600 	    edif_cell_pinteger(cell, "LPM_Size",   wid_z);
601       }
602 
603 
604       ref = edif_cellref_create(edf, cell);
605 
606 	/* Connect the pins of the instance to the nexa. Access the
607 	   cell pins by name. */
608       for (idx = 0 ;  idx < wid_r ;  idx += 1) {
609 	    unsigned pin;
610 
611 	    sprintf(cellname, "Result%u", idx);
612 	    pin = edif_cell_port_byname(cell, cellname);
613 
614 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
615 	    edif_add_to_joint(jnt, ref, pin);
616       }
617 
618       for (idx = 0 ;  idx < wid_s ;  idx += 1) {
619 	    unsigned pin;
620 
621 	    sprintf(cellname, "Sel%u", idx);
622 	    pin = edif_cell_port_byname(cell, cellname);
623 
624 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_select(net, idx));
625 	    edif_add_to_joint(jnt, ref, pin);
626       }
627 
628       for (idx = 0 ;  idx < wid_z ;  idx += 1) {
629 	    for (rdx = 0 ;  rdx < wid_r ;  rdx += 1) {
630 		  unsigned pin;
631 
632 		  sprintf(cellname, "Data%ux%u", idx, rdx);
633 		  pin = edif_cell_port_byname(cell, cellname);
634 
635 		  jnt = edif_joint_of_nexus(edf, ivl_lpm_data2(net, idx, rdx));
636 		  edif_add_to_joint(jnt, ref, pin);
637 	    }
638       }
639 }
640 
lpm_show_add(ivl_lpm_t net)641 static void lpm_show_add(ivl_lpm_t net)
642 {
643       unsigned idx;
644       unsigned cell_width;
645       char cellname[32];
646       edif_cell_t cell;
647       edif_cellref_t ref;
648       edif_joint_t jnt;
649 
650       const char*type = "ADD";
651 
652       if (ivl_lpm_type(net) == IVL_LPM_SUB)
653 	    type = "SUB";
654 
655 	/* Figure out the width of the cell. Normally, it is the LPM
656 	   width known by IVL. But if the top data input bits are
657 	   unconnected, then we really have a width one less, and we
658 	   can use the cout to fill out the output width. */
659       cell_width = ivl_lpm_width(net);
660       if ( (ivl_lpm_data(net,cell_width-1) == 0)
661 	   && (ivl_lpm_datab(net,cell_width-1) == 0) )
662 	    cell_width -= 1;
663 
664 	/* Find the correct ADD/SUB device in the library, search by
665 	   name. If the device is not there, then create it and put it
666 	   in the library. */
667       sprintf(cellname, "%s%u", type, cell_width);
668       cell = edif_xlibrary_findcell(xlib, cellname);
669 
670       if (cell == 0) {
671 	    unsigned pins = cell_width * 3 + 1;
672 
673 	    cell = edif_xcell_create(xlib, strdup(cellname), pins);
674 
675 	    for (idx = 0 ;  idx < cell_width ;  idx += 1) {
676 
677 		  sprintf(cellname, "Result%u", idx);
678 		  edif_cell_portconfig(cell, idx*3+0, strdup(cellname),
679 				       IVL_SIP_OUTPUT);
680 
681 		  sprintf(cellname, "DataA%u", idx);
682 		  edif_cell_portconfig(cell, idx*3+1, strdup(cellname),
683 				       IVL_SIP_INPUT);
684 
685 		  sprintf(cellname, "DataB%u", idx);
686 		  edif_cell_portconfig(cell, idx*3+2, strdup(cellname),
687 				       IVL_SIP_INPUT);
688 	    }
689 
690 	    edif_cell_portconfig(cell, pins-1, "Cout", IVL_SIP_OUTPUT);
691 
692 	    edif_cell_pstring(cell,  "LPM_Type",      "LPM_ADD_SUB");
693 	    edif_cell_pstring(cell,  "LPM_Direction", type);
694 	    edif_cell_pinteger(cell, "LPM_Width",     ivl_lpm_width(net));
695       }
696 
697       ref = edif_cellref_create(edf, cell);
698 
699 	/* Connect the pins of the instance to the nexa. Access the
700 	   cell pins by name. */
701       for (idx = 0 ;  idx < cell_width ;  idx += 1) {
702 	    unsigned pin;
703 
704 	    sprintf(cellname, "Result%u", idx);
705 	    pin = edif_cell_port_byname(cell, cellname);
706 
707 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
708 	    edif_add_to_joint(jnt, ref, pin);
709 
710 	    sprintf(cellname, "DataA%u", idx);
711 	    pin = edif_cell_port_byname(cell, cellname);
712 
713 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx));
714 	    edif_add_to_joint(jnt, ref, pin);
715 
716 	    sprintf(cellname, "DataB%u", idx);
717 	    pin = edif_cell_port_byname(cell, cellname);
718 
719 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_datab(net, idx));
720 	    edif_add_to_joint(jnt, ref, pin);
721       }
722 
723       if (cell_width < ivl_lpm_width(net)) {
724 	    unsigned pin = edif_cell_port_byname(cell, "Cout");
725 
726 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, cell_width));
727 	    edif_add_to_joint(jnt, ref, pin);
728       }
729 }
730 
lpm_show_mult(ivl_lpm_t net)731 static void lpm_show_mult(ivl_lpm_t net)
732 {
733       char name[64];
734       unsigned idx;
735 
736       edif_cell_t cell;
737       edif_cellref_t ref;
738 
739       sprintf(name, "mult%u", ivl_lpm_width(net));
740       cell = edif_xlibrary_findcell(xlib, name);
741 
742       if (cell == 0) {
743 	    cell = edif_xcell_create(xlib, strdup(name),
744 				     3 * ivl_lpm_width(net));
745 
746 	    for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
747 
748 		  sprintf(name, "Result%u", idx);
749 		  edif_cell_portconfig(cell, idx*3+0,
750 				       strdup(name),
751 				       IVL_SIP_OUTPUT);
752 
753 		  sprintf(name, "DataA%u", idx);
754 		  edif_cell_portconfig(cell, idx*3+1,
755 				       strdup(name),
756 				       IVL_SIP_INPUT);
757 
758 		  sprintf(name, "DataB%u", idx);
759 		  edif_cell_portconfig(cell, idx*3+2,
760 				       strdup(name),
761 				       IVL_SIP_INPUT);
762 	    }
763 
764 	    edif_cell_pstring(cell,  "LPM_Type",  "LPM_MULT");
765 	    edif_cell_pinteger(cell, "LPM_WidthP", ivl_lpm_width(net));
766 	    edif_cell_pinteger(cell, "LPM_WidthA", ivl_lpm_width(net));
767 	    edif_cell_pinteger(cell, "LPM_WidthB", ivl_lpm_width(net));
768       }
769 
770       ref = edif_cellref_create(edf, cell);
771 
772       for (idx = 0 ;  idx < ivl_lpm_width(net) ;  idx += 1) {
773 	    unsigned pin;
774 	    ivl_nexus_t nex;
775 	    edif_joint_t jnt;
776 
777 	    sprintf(name, "Result%u", idx);
778 	    pin = edif_cell_port_byname(cell, name);
779 
780 	    jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx));
781 	    edif_add_to_joint(jnt, ref, pin);
782 
783 	    if ( (nex = ivl_lpm_data(net, idx)) ) {
784 		  sprintf(name, "DataA%u", idx);
785 		  pin = edif_cell_port_byname(cell, name);
786 
787 		  jnt = edif_joint_of_nexus(edf, nex);
788 		  edif_add_to_joint(jnt, ref, pin);
789 	    }
790 
791 	    if ( (nex = ivl_lpm_datab(net, idx)) ) {
792 		  sprintf(name, "DataB%u", idx);
793 		  pin = edif_cell_port_byname(cell, name);
794 
795 		  jnt = edif_joint_of_nexus(edf, nex);
796 		  edif_add_to_joint(jnt, ref, pin);
797 	    }
798       }
799 
800 }
801 
lpm_show_constant(ivl_net_const_t net)802 static void lpm_show_constant(ivl_net_const_t net)
803 {
804       edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0");
805       edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1");
806       edif_cellref_t ref0 = 0, ref1 = 0;
807 
808       const char*bits;
809       unsigned idx;
810 
811       if (cell0 == 0) {
812 	    cell0 = edif_xcell_create(xlib, "cell0", 1);
813 	    edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT);
814 
815 	    edif_cell_pstring(cell0,  "LPM_Type",   "LPM_CONSTANT");
816 	    edif_cell_pinteger(cell0, "LPM_Width",  1);
817 	    edif_cell_pinteger(cell0, "LPM_CValue", 0);
818       }
819 
820       if (cell1 == 0) {
821 	    cell1 = edif_xcell_create(xlib, "cell1", 1);
822 	    edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT);
823 
824 	    edif_cell_pstring(cell1,  "LPM_Type",   "LPM_CONSTANT");
825 	    edif_cell_pinteger(cell1, "LPM_Width",  1);
826 	    edif_cell_pinteger(cell1, "LPM_CValue", 1);
827       }
828 
829       bits = ivl_const_bits(net);
830       for (idx = 0 ;  idx < ivl_const_pins(net) ;  idx += 1) {
831 	    if (bits[idx] == '1') {
832 		  if (ref1 == 0)
833 			ref1 = edif_cellref_create(edf, cell1);
834 
835 	    } else {
836 		  if (ref0 == 0)
837 			ref0 = edif_cellref_create(edf, cell0);
838 	    }
839       }
840 
841       for (idx = 0 ;  idx < ivl_const_pins(net) ;  idx += 1) {
842 	    edif_joint_t jnt;
843 
844 	    jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx));
845 	    if (bits[idx] == '1')
846 		  edif_add_to_joint(jnt, ref1, 0);
847 	    else
848 		  edif_add_to_joint(jnt, ref0, 0);
849       }
850 
851 }
852 
853 
854 const struct device_s d_lpm_edif = {
855       lpm_show_header,
856       lpm_show_footer,
857       0,
858       0,
859       lpm_logic,
860       lpm_show_dff, /* show_dff */
861       0,
862       0,
863       0,
864       0, /* show_cmp_gt */
865       lpm_show_mux, /* show_mux */
866       lpm_show_add, /* show_add */
867       lpm_show_add, /* show_sub */
868       0, /* show_shiftl */
869       0, /* show_shiftr */
870       lpm_show_mult, /* show_mult */
871       lpm_show_constant /* show_constant */
872 };
873