Add file and line information for parameters, etc.
[sverilog.git] / tgt-vvp / vvp_scope.c
blob2d1b6d1849ce5aaf1a07b72249c42a90237c5420
1 /*
2 * Copyright (c) 2001-2008 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
20 # include "vvp_priv.h"
21 #ifdef HAVE_MALLOC_H
22 # include <malloc.h>
23 #endif
24 # include <stdlib.h>
25 # include <math.h>
26 # include <string.h>
27 # include <inttypes.h>
28 # include <assert.h>
30 struct vvp_nexus_data {
31 /* draw_net_input uses this */
32 const char*net_input;
33 unsigned drivers_count;
34 int flags;
35 /* draw_net_in_scope uses these to identify the controlling word. */
36 ivl_signal_t net;
37 unsigned net_word;
39 #define VVP_NEXUS_DATA_STR 0x0001
42 static struct vvp_nexus_data*new_nexus_data()
44 struct vvp_nexus_data*data = calloc(1, sizeof(struct vvp_nexus_data));
45 return data;
49 * Escape non-symbol characters in ids, and quotes in strings.
52 inline static char hex_digit(unsigned i)
54 i &= 0xf;
55 return i>=10 ? i-10+'A' : i+'0';
58 const char *vvp_mangle_id(const char *id)
60 static char *out = 0x0;
61 static size_t out_len;
63 int nesc = 0;
64 int iout = 0;
65 const char *inp = id;
67 const char nosym[] = "!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~";
69 char *se = strpbrk(inp, nosym);
70 if (!se)
71 return id;
73 do {
74 int n = se - inp;
75 unsigned int nlen = strlen(id) + 4*(++nesc) + 1;
76 if (out_len < nlen) {
77 out = realloc(out, nlen);
78 assert(out);
79 out_len = nlen;
81 if (n) {
82 strncpy(out+iout, inp, n);
83 iout += n;
85 inp += n+1;
86 out[iout++] = '\\';
87 switch (*se) {
88 case '\\':
89 case '/':
90 case '<':
91 case '>':
92 out[iout++] = *se;
93 break;
94 default:
95 out[iout++] = 'x';
96 out[iout++] = hex_digit(*se >> 4);
97 out[iout++] = hex_digit(*se);
98 break;
101 se = strpbrk(inp, nosym);
102 } while (se);
104 strcpy(out+iout, inp);
105 return out;
108 const char *vvp_mangle_name(const char *id)
110 static char *out = 0x0;
111 static size_t out_len;
113 int nesc = 0;
114 int iout = 0;
115 const char *inp = id;
117 const char nosym[] = "\"\\";
119 char *se = strpbrk(inp, nosym);
120 if (!se)
121 return id;
123 do {
124 int n = se - inp;
125 unsigned int nlen = strlen(id) + 2*(++nesc) + 1;
126 if (out_len < nlen) {
127 out = realloc(out, nlen);
128 assert(out);
129 out_len = nlen;
131 if (n) {
132 strncpy(out+iout, inp, n);
133 iout += n;
135 inp += n+1;
136 out[iout++] = '\\';
137 out[iout++] = *se;
139 se = strpbrk(inp, nosym);
140 } while (se);
142 strcpy(out+iout, inp);
143 return out;
146 static void draw_C4_repeated_constant(char bit_char, unsigned width)
148 unsigned idx;
150 fprintf(vvp_out, "C4<");
151 for (idx = 0 ; idx < width ; idx += 1)
152 fprintf(vvp_out, "%c", bit_char);
154 fprintf(vvp_out, ">");
157 static void str_repeat(char*buf, const char*str, unsigned rpt)
159 unsigned idx;
160 size_t len = strlen(str);
161 for (idx = 0 ; idx < rpt ; idx += 1) {
162 strcpy(buf, str);
163 buf += len;
167 /* REMOVE ME: vvp_signal_label should not be used. DEAD CODE
168 * Given a signal, generate a string name that is suitable for use as
169 * a label. The only rule is that the same signal will always have the
170 * same label. The result is stored in static memory, so remember to
171 * copy it out.
173 const char* vvp_signal_label(ivl_signal_t sig)
175 static char buf[32];
176 sprintf(buf, "%p", sig);
177 return buf;
180 ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word)
182 unsigned idx;
183 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
184 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
185 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
186 if (sig == 0)
187 continue;
188 if (ivl_signal_local(sig))
189 continue;
190 *word = ivl_nexus_ptr_pin(ptr);
191 return sig;
194 return 0;
197 ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
199 unsigned idx;
200 ivl_signal_type_t out = IVL_SIT_TRI;
202 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
203 ivl_signal_type_t stype;
204 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
205 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
206 if (sig == 0)
207 continue;
209 stype = ivl_signal_type(sig);
210 if (stype == IVL_SIT_REG)
211 continue;
212 if (stype == IVL_SIT_TRI)
213 continue;
214 if (stype == IVL_SIT_NONE)
215 continue;
216 out = stype;
219 return out;
222 unsigned width_of_nexus(ivl_nexus_t nex)
224 unsigned idx;
226 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
227 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
228 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
229 if (sig != 0)
230 return ivl_signal_width(sig);
233 return 0;
236 ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex)
238 unsigned idx;
239 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
240 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
241 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
242 if (sig != 0)
243 return ivl_signal_data_type(sig);
246 /* shouldn't happen! */
247 return IVL_VT_NO_TYPE;
251 ivl_nexus_ptr_t ivl_logic_pin_ptr(ivl_net_logic_t net, unsigned pin)
253 ivl_nexus_t nex = ivl_logic_pin(net, pin);
254 unsigned idx;
256 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
257 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
258 ivl_net_logic_t tmp = ivl_nexus_ptr_log(ptr);
259 if (tmp == 0)
260 continue;
261 if (tmp != net)
262 continue;
263 if (ivl_nexus_ptr_pin(ptr) != pin)
264 continue;
266 return ptr;
268 assert(0);
269 return 0;
272 const char*drive_string(ivl_drive_t drive)
274 switch (drive) {
275 case IVL_DR_HiZ:
276 return "";
277 case IVL_DR_SMALL:
278 return "sm";
279 case IVL_DR_MEDIUM:
280 return "me";
281 case IVL_DR_WEAK:
282 return "we";
283 case IVL_DR_LARGE:
284 return "la";
285 case IVL_DR_PULL:
286 return "pu";
287 case IVL_DR_STRONG:
288 return "";
289 case IVL_DR_SUPPLY:
290 return "su";
293 return "";
298 * The draw_scope function draws the major functional items within a
299 * scope. This includes the scopes themselves, of course. All the
300 * other functions in this file are in support of that task.
305 * NEXUS
306 * ivl builds up the netlist into objects connected together by
307 * ivl_nexus_t objects. The nexus receives all the drivers of the
308 * point in the net and resolves the value. The result is then sent to
309 * all the nets that are connected to the nexus. The nets, then, are
310 * read to get the value of the nexus.
312 * NETS
313 * Nets are interesting and special, because a nexus may be connected
314 * to several of them at once. This can happen, for example, as an
315 * artifact of module port connects, where the inside and the outside
316 * of the module are connected through an in-out port. (In fact, ivl
317 * will simply connect signals that are bound through a port, because
318 * the input/output/inout properties are enforced as compile time.)
320 * This case is handled by choosing one to receive the value of the
321 * nexus. This one then feeds to another net at the nexus, and so
322 * on. The last net is selected as the output of the nexus.
326 * This tests a bufz device against an output receiver, and determines
327 * if the device can be skipped. If this function returns true, then a
328 * gate will be generated for this node. Otherwise, the code generator
329 * will connect its input to its output and skip the gate.
331 static int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
333 ivl_nexus_t in_n;
334 unsigned idx;
336 /* These are the drives we expect. */
337 ivl_drive_t dr0 = ivl_nexus_ptr_drive0(nptr);
338 ivl_drive_t dr1 = ivl_nexus_ptr_drive1(nptr);
339 int drive_count = 0;
341 /* If the gate carries a delay, it must remain. */
342 if (ivl_logic_delay(net, 0) != 0)
343 return 0;
345 /* If the input is connected to the output, then do not elide
346 the gate. This is some sort of cycle. */
347 if (ivl_logic_pin(net, 0) == ivl_logic_pin(net, 1))
348 return 0;
350 in_n = ivl_logic_pin(net, 1);
351 for (idx = 0 ; idx < ivl_nexus_ptrs(in_n) ; idx += 1) {
352 ivl_nexus_ptr_t in_np = ivl_nexus_ptr(in_n, idx);
353 if (ivl_nexus_ptr_log(in_np) == net)
354 continue;
356 /* If the driver for the source does not match the
357 expected drive, then we need to keep the bufz. This
358 test also catches the case that the input device is
359 really also an input, as that device will have a
360 drive of HiZ. We need to keep BUFZ devices in that
361 case in order to prevent back-flow of data. */
362 if (ivl_nexus_ptr_drive0(in_np) != dr0)
363 return 0;
364 if (ivl_nexus_ptr_drive1(in_np) != dr1)
365 return 0;
367 drive_count += 1;
370 /* If the BUFZ input has multiple drivers on its input, then
371 we need to keep this device in order to hide the
372 resolution. */
373 if (drive_count != 1)
374 return 0;
376 return 1;
380 * Given a nexus, look for a signal that has module delay
381 * paths. Return that signal. (There should be no more than 1.) If we
382 * don't find any, then return nil.
384 static ivl_signal_t find_modpath(ivl_nexus_t nex)
386 unsigned idx;
387 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
388 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx);
389 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
390 if (sig == 0)
391 continue;
392 if (ivl_signal_npath(sig) == 0)
393 continue;
395 return sig;
398 return 0;
401 static char* draw_C4_to_string(ivl_net_const_t cptr)
403 const char*bits = ivl_const_bits(cptr);
404 unsigned idx;
406 size_t result_len = 5 + ivl_const_width(cptr);
407 char*result = malloc(result_len);
408 char*dp = result;
409 strcpy(dp, "C4<");
410 dp += strlen(dp);
412 for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
413 char bitchar = bits[ivl_const_width(cptr)-idx-1];
414 *dp++ = bitchar;
415 assert((dp - result) < result_len);
418 strcpy(dp, ">");
419 return result;
422 static char* draw_C8_to_string(ivl_net_const_t cptr,
423 ivl_drive_t dr0, ivl_drive_t dr1)
425 size_t nresult = 5 + 3*ivl_const_width(cptr);
426 char*result = malloc(nresult);
427 const char*bits = ivl_const_bits(cptr);
428 unsigned idx;
430 char dr0c = "01234567"[dr0];
431 char dr1c = "01234567"[dr1];
432 char*dp = result;
434 strcpy(dp, "C8<");
435 dp += strlen(dp);
437 for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
438 switch (bits[ivl_const_width(cptr)-idx-1]) {
439 case '0':
440 *dp++ = dr0c;
441 *dp++ = dr0c;
442 *dp++ = '0';
443 break;
444 case '1':
445 *dp++ = dr1c;
446 *dp++ = dr1c;
447 *dp++ = '1';
448 break;
449 case 'x':
450 case 'X':
451 *dp++ = dr0c;
452 *dp++ = dr1c;
453 *dp++ = 'x';
454 break;
455 case 'z':
456 case 'Z':
457 *dp++ = '0';
458 *dp++ = '0';
459 *dp++ = 'z';
460 break;
461 default:
462 assert(0);
463 break;
465 assert(dp - result < nresult);
468 strcpy(dp, ">");
469 return result;
472 static char* draw_Cr_to_string(double value)
474 char tmp[256];
476 uint64_t mant = 0;
478 if (isinf(value)) {
479 if (value > 0)
480 snprintf(tmp, sizeof(tmp), "Cr<m0g3fff>");
481 else
482 snprintf(tmp, sizeof(tmp), "Cr<m0g7fff>");
483 return strdup(tmp);
486 int sign = 0;
487 if (value < 0) {
488 sign = 0x4000;
489 value *= -1;
492 int expo;
493 double fract = frexp(value, &expo);
494 fract = ldexp(fract, 63);
495 mant = fract;
496 expo -= 63;
498 int vexp = expo + 0x1000;
499 assert(vexp >= 0);
500 assert(vexp < 0x2000);
501 vexp += sign;
503 snprintf(tmp, sizeof(tmp), "Cr<m%" PRIx64 "g%x>", mant, vexp);
504 return strdup(tmp);
508 * This function takes a nexus and looks for an input functor. It then
509 * draws to the output a string that represents that functor. What we
510 * are trying to do here is find the input to the net that is attached
511 * to this nexus.
514 static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
516 unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
517 ivl_net_const_t cptr;
518 ivl_net_logic_t lptr;
519 ivl_signal_t sptr;
520 ivl_lpm_t lpm;
522 lptr = ivl_nexus_ptr_log(nptr);
523 if (lptr && (ivl_logic_type(lptr) == IVL_LO_BUFZ) && (nptr_pin == 0))
524 do {
525 if (! can_elide_bufz(lptr, nptr))
526 break;
528 return strdup(draw_net_input(ivl_logic_pin(lptr, 1)));
529 } while(0);
531 /* If this is a pulldown device, then there is a single pin
532 that drives a constant value to the entire width of the
533 vector. The driver normally drives a pull0 value, so a C8<>
534 constant is appropriate, but if the drive is really strong,
535 then we can draw a C4<> constant instead. */
536 if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
537 if (ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) {
538 size_t result_len = ivl_logic_width(lptr) + 5;
539 char*result = malloc(result_len);
540 char*dp = result;
541 strcpy(dp, "C4<");
542 dp += strlen(dp);
543 str_repeat(dp, "0", ivl_logic_width(lptr));
544 dp += ivl_logic_width(lptr);
545 *dp++ = '>';
546 *dp = 0;
547 assert((dp-result) <= result_len);
548 return result;
549 } else {
550 char val[4];
551 size_t result_len = 3*ivl_logic_width(lptr) + 5;
552 char*result = malloc(result_len);
553 char*dp = result;
555 val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
556 val[1] = val[0];
557 val[2] = '0';
558 val[3] = 0;
560 strcpy(dp, "C8<");
561 dp += strlen(dp);
562 str_repeat(dp, val, ivl_logic_width(lptr));
563 dp += 3*ivl_logic_width(lptr);
564 *dp++ = '>';
565 *dp = 0;
566 assert((dp-result) <= result_len);
567 return result;
571 if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
572 if (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG) {
573 size_t result_len = 5 + ivl_logic_width(lptr);
574 char*result = malloc(result_len);
575 char*dp = result;
576 strcpy(dp, "C4<");
577 dp += strlen(dp);
578 str_repeat(dp, "1", ivl_logic_width(lptr));
579 dp += ivl_logic_width(lptr);
580 *dp++ = '>';
581 *dp = 0;
582 assert((dp-result) <= result_len);
583 return result;
584 } else {
585 char val[4];
586 size_t result_len = 5 + 3*ivl_logic_width(lptr);
587 char*result = malloc(result_len);
588 char*dp = result;
590 val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
591 val[1] = val[0];
592 val[2] = '1';
593 val[3] = 0;
595 strcpy(dp, "C8<");
596 dp += strlen(dp);
597 str_repeat(dp, val, ivl_logic_width(lptr));
598 dp += 3*ivl_logic_width(lptr);
599 *dp++ = '>';
600 *dp = 0;
601 assert((dp-result) <= result_len);
602 return result;
606 if (lptr && (nptr_pin == 0)) {
607 char tmp[128];
608 snprintf(tmp, sizeof tmp, "L_%p", lptr);
609 return strdup(tmp);
612 sptr = ivl_nexus_ptr_sig(nptr);
613 if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
614 char tmp[128];
615 /* Input is a .var. This device may be a non-zero pin
616 because it may be an array of reg vectors. */
617 snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin);
618 return strdup(tmp);
621 cptr = ivl_nexus_ptr_con(nptr);
622 if (cptr) {
623 /* Constants should have exactly 1 pin, with a literal value. */
624 assert(nptr_pin == 0);
625 char *result = 0;
627 switch (ivl_const_type(cptr)) {
628 case IVL_VT_LOGIC:
629 case IVL_VT_BOOL:
630 if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG)
631 && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) {
633 result = draw_C4_to_string(cptr);
635 } else {
636 result = draw_C8_to_string(cptr,
637 ivl_nexus_ptr_drive0(nptr),
638 ivl_nexus_ptr_drive1(nptr));
640 break;
642 case IVL_VT_REAL:
643 result = draw_Cr_to_string(ivl_const_real(cptr));
644 break;
646 default:
647 assert(0);
648 break;
651 ivl_expr_t d_rise = ivl_const_delay(cptr, 0);
652 ivl_expr_t d_fall = ivl_const_delay(cptr, 1);
653 ivl_expr_t d_decay = ivl_const_delay(cptr, 2);
655 /* We have a delayed constant, so we need to build some code. */
656 if (d_rise != 0) {
657 assert(number_is_immediate(d_rise, 64));
658 assert(number_is_immediate(d_fall, 64));
659 assert(number_is_immediate(d_decay, 64));
661 fprintf(vvp_out, "L_%p/d .functor BUFZ 1, %s, "
662 "C4<0>, C4<0>, C4<0>;\n", cptr, result);
664 fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
665 cptr, get_number_immediate(d_rise),
666 get_number_immediate(d_rise),
667 get_number_immediate(d_rise), cptr);
669 free(result);
670 char tmp[128];
671 snprintf(tmp, sizeof tmp, "L_%p", cptr);
672 result = strdup(tmp);
675 return result;
678 lpm = ivl_nexus_ptr_lpm(nptr);
679 if (lpm) switch (ivl_lpm_type(lpm)) {
681 case IVL_LPM_FF:
682 case IVL_LPM_ADD:
683 case IVL_LPM_ARRAY:
684 case IVL_LPM_CONCAT:
685 case IVL_LPM_CMP_EEQ:
686 case IVL_LPM_CMP_EQ:
687 case IVL_LPM_CMP_GE:
688 case IVL_LPM_CMP_GT:
689 case IVL_LPM_CMP_NE:
690 case IVL_LPM_CMP_NEE:
691 case IVL_LPM_RE_AND:
692 case IVL_LPM_RE_OR:
693 case IVL_LPM_RE_XOR:
694 case IVL_LPM_RE_NAND:
695 case IVL_LPM_RE_NOR:
696 case IVL_LPM_RE_XNOR:
697 case IVL_LPM_SFUNC:
698 case IVL_LPM_SHIFTL:
699 case IVL_LPM_SHIFTR:
700 case IVL_LPM_SIGN_EXT:
701 case IVL_LPM_SUB:
702 case IVL_LPM_MULT:
703 case IVL_LPM_MUX:
704 case IVL_LPM_POW:
705 case IVL_LPM_DIVIDE:
706 case IVL_LPM_MOD:
707 case IVL_LPM_UFUNC:
708 case IVL_LPM_PART_VP:
709 case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
710 case IVL_LPM_REPEAT:
711 if (ivl_lpm_q(lpm, 0) == nex) {
712 char tmp[128];
713 snprintf(tmp, sizeof tmp, "L_%p", lpm);
714 return strdup(tmp);
716 break;
718 case IVL_LPM_PART_BI:
719 if (ivl_lpm_q(lpm, 0) == nex) {
720 char tmp[128];
721 snprintf(tmp, sizeof tmp, "L_%p/P", lpm);
722 return strdup(tmp);
723 } else if (ivl_lpm_data(lpm,0) == nex) {
724 char tmp[128];
725 snprintf(tmp, sizeof tmp, "L_%p/V", lpm);
726 return strdup(tmp);
728 break;
731 fprintf(stderr, "internal error: no input to nexus %s\n",
732 ivl_nexus_name(nex));
733 assert(0);
734 return strdup("C<z>");
737 static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr)
739 if (ivl_nexus_ptr_drive0(nptr) != IVL_DR_STRONG)
740 return 1;
741 if (ivl_nexus_ptr_drive1(nptr) != IVL_DR_STRONG)
742 return 1;
744 ivl_net_logic_t log = ivl_nexus_ptr_log(nptr);
745 if (log != 0) {
746 /* These logic gates are able to generate unusual
747 strength values and so their outputs are considered
748 strength aware. */
749 if (ivl_logic_type(log) == IVL_LO_BUFIF0)
750 return 1;
751 if (ivl_logic_type(log) == IVL_LO_BUFIF1)
752 return 1;
753 if (ivl_logic_type(log) == IVL_LO_PMOS)
754 return 1;
755 if (ivl_logic_type(log) == IVL_LO_NMOS)
756 return 1;
757 if (ivl_logic_type(log) == IVL_LO_CMOS)
758 return 1;
761 return 0;
765 * This function draws the input to a net into a string. What that
766 * means is that it returns a static string that can be used to
767 * represent a resolved driver to a nexus. If there are multiple
768 * drivers to the nexus, then it writes out the resolver declarations
769 * needed to perform strength resolution.
771 * The string that this returns is malloced, and that means that the
772 * caller must free the string or store it permanently. This function
773 * does *not* check for a previously calculated string. Use the
774 * draw_net_input for the general case.
776 /* Omit LPMPART_BI device pin-data(0) drivers. */
777 # define OMIT_PART_BI_DATA 0x0001
779 static char* draw_net_input_x(ivl_nexus_t nex,
780 ivl_nexus_ptr_t omit_ptr, int omit_flags,
781 struct vvp_nexus_data*nex_data)
783 ivl_signal_type_t res;
784 char result[512];
785 unsigned idx;
786 int level;
787 unsigned ndrivers = 0;
788 static ivl_nexus_ptr_t *drivers = 0x0;
789 static unsigned adrivers = 0;
791 const char*resolv_type;
793 char*nex_private = 0;
795 /* Accumulate nex_data flags. */
796 int nex_flags = 0;
798 res = signal_type_of_nexus(nex);
799 switch (res) {
800 case IVL_SIT_TRI:
801 resolv_type = "tri";
802 break;
803 case IVL_SIT_TRI0:
804 resolv_type = "tri0";
805 nex_flags |= VVP_NEXUS_DATA_STR;
806 break;
807 case IVL_SIT_TRI1:
808 resolv_type = "tri1";
809 nex_flags |= VVP_NEXUS_DATA_STR;
810 break;
811 case IVL_SIT_TRIAND:
812 resolv_type = "triand";
813 break;
814 case IVL_SIT_TRIOR:
815 resolv_type = "trior";
816 break;
817 default:
818 fprintf(stderr, "vvp.tgt: Unsupported signal type: %u\n", res);
819 assert(0);
820 resolv_type = "tri";
821 break;
825 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
826 ivl_lpm_t lpm_tmp;
827 ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, idx);
829 /* If we are supposed to skip LPM_PART_BI data pins,
830 check that this driver is that. */
831 if ((omit_flags&OMIT_PART_BI_DATA)
832 && (lpm_tmp = ivl_nexus_ptr_lpm(nptr))
833 && (nex == ivl_lpm_data(lpm_tmp,0)))
834 continue;
836 if (nptr == omit_ptr)
837 continue;
839 /* Skip input only pins. */
840 if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_HiZ)
841 && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_HiZ))
842 continue;
844 /* Mark the strength-aware flag if the driver can
845 generate values other than the standard "6"
846 strength. */
847 if (nexus_drive_is_strength_aware(nptr))
848 nex_flags |= VVP_NEXUS_DATA_STR;
850 /* Save this driver. */
851 if (ndrivers >= adrivers) {
852 adrivers += 4;
853 drivers = realloc(drivers, adrivers*sizeof(ivl_nexus_ptr_t));
854 assert(drivers);
856 drivers[ndrivers] = nptr;
857 ndrivers += 1;
860 /* If the caller is collecting nexus information, then save
861 the nexus driver count in the nex_data. */
862 if (nex_data) {
863 nex_data->drivers_count = ndrivers;
864 nex_data->flags |= nex_flags;
867 /* If the nexus has no drivers, then send a constant HiZ into
868 the net. */
869 if (ndrivers == 0) {
870 unsigned idx, wid = width_of_nexus(nex);
871 char*tmp = malloc(wid + 5);
872 nex_private = tmp;
873 strcpy(tmp, "C4<");
874 tmp += strlen(tmp);
875 switch (res) {
876 case IVL_SIT_TRI:
877 for (idx = 0 ; idx < wid ; idx += 1)
878 *tmp++ = 'z';
879 break;
880 case IVL_SIT_TRI0:
881 for (idx = 0 ; idx < wid ; idx += 1)
882 *tmp++ = '0';
883 break;
884 case IVL_SIT_TRI1:
885 for (idx = 0 ; idx < wid ; idx += 1)
886 *tmp++ = '1';
887 break;
888 default:
889 assert(0);
891 *tmp++ = '>';
892 *tmp = 0;
893 return nex_private;
897 /* If the nexus has exactly one driver, then simply draw
898 it. Note that this will *not* work if the nexus is not a
899 TRI type nexus. */
900 if (ndrivers == 1 && res == IVL_SIT_TRI) {
901 ivl_signal_t path_sig = find_modpath(nex);
902 if (path_sig) {
903 char*nex_str = draw_net_input_drive(nex, drivers[0]);
904 char modpath_label[64];
905 snprintf(modpath_label, sizeof modpath_label,
906 "V_%p/m", path_sig);
907 nex_private = strdup(modpath_label);
908 draw_modpath(path_sig, nex_str);
910 } else {
911 nex_private = draw_net_input_drive(nex, drivers[0]);
913 return nex_private;
916 level = 0;
917 while (ndrivers) {
918 unsigned int inst;
919 for (inst = 0; inst < ndrivers; inst += 4) {
920 if (ndrivers > 4)
921 fprintf(vvp_out, "RS_%p/%d/%d .resolv tri",
922 nex, level, inst);
923 else
924 fprintf(vvp_out, "RS_%p .resolv %s",
925 nex, resolv_type);
927 for (idx = inst; idx < ndrivers && idx < inst+4; idx += 1) {
928 if (level) {
929 fprintf(vvp_out, ", RS_%p/%d/%d",
930 nex, level - 1, idx*4);
931 } else {
932 char*drive = draw_net_input_drive(nex, drivers[idx]);
933 fprintf(vvp_out, ", %s", drive);
934 free(drive);
937 for ( ; idx < inst+4 ; idx += 1) {
938 fprintf(vvp_out, ", ");
939 draw_C4_repeated_constant('z',width_of_nexus(nex));
942 fprintf(vvp_out, ";\n");
944 if (ndrivers > 4)
945 ndrivers = (ndrivers+3) / 4;
946 else
947 ndrivers = 0;
948 level += 1;
951 sprintf(result, "RS_%p", nex);
952 nex_private = strdup(result);
953 return nex_private;
957 * Get a cached description of the nexus input, or create one if this
958 * nexus has not been cached yet. This is a wrapper for the common
959 * case call to draw_net_input_x.
961 const char*draw_net_input(ivl_nexus_t nex)
963 struct vvp_nexus_data*nex_data = (struct vvp_nexus_data*)
964 ivl_nexus_get_private(nex);
966 /* If this nexus already has a label, then its input is
967 already figured out. Just return the existing label. */
968 if (nex_data && nex_data->net_input)
969 return nex_data->net_input;
971 if (nex_data == 0) {
972 nex_data = new_nexus_data();
973 ivl_nexus_set_private(nex, nex_data);
976 assert(nex_data->net_input == 0);
977 nex_data->net_input = draw_net_input_x(nex, 0, 0, nex_data);
979 return nex_data->net_input;
982 const char*draw_input_from_net(ivl_nexus_t nex)
984 static char result[32];
985 unsigned word;
987 ivl_signal_t sig = signal_of_nexus(nex, &word);
988 if (sig == 0)
989 return draw_net_input(nex);
991 snprintf(result, sizeof result, "v%p_%u", sig, word);
992 return result;
997 * This function draws a reg/int/variable in the scope. This is a very
998 * simple device to draw as there are no inputs to connect so no need
999 * to scan the nexus. We do have to account for the possibility that
1000 * the device is arrayed, though, by making a node for each array element.
1002 static void draw_reg_in_scope(ivl_signal_t sig)
1004 int msb = ivl_signal_msb(sig);
1005 int lsb = ivl_signal_lsb(sig);
1007 const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
1008 ivl_signal_signed(sig)? "/s" : "";
1009 const char*local_flag = ivl_signal_local(sig)? "*" : "";
1011 switch (ivl_signal_data_type(sig)) {
1012 case IVL_VT_REAL:
1013 datatype_flag = "/real";
1014 break;
1015 default:
1016 break;
1019 /* If the reg objects are collected into an array, then first
1020 write out the .array record to declare the array indices. */
1021 if (ivl_signal_dimensions(sig) > 0) {
1022 unsigned word_count = ivl_signal_array_count(sig);
1023 int last = ivl_signal_array_base(sig)+word_count-1;
1024 int first = ivl_signal_array_base(sig);
1025 fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
1026 sig, datatype_flag,
1027 vvp_mangle_name(ivl_signal_basename(sig)),
1028 last, first, msb, lsb);
1030 } else {
1032 fprintf(vvp_out, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
1033 sig, datatype_flag, local_flag,
1034 vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb,
1035 ivl_signal_local(sig)? " Local signal" : "");
1041 * This function draws a net. This is a bit more complicated as we
1042 * have to find an appropriate functor to connect to the input.
1044 static void draw_net_in_scope(ivl_signal_t sig)
1046 int msb = ivl_signal_msb(sig);
1047 int lsb = ivl_signal_lsb(sig);
1049 const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
1050 const char*local_flag = ivl_signal_local(sig)? "*" : "";
1051 unsigned iword;
1053 switch (ivl_signal_data_type(sig)) {
1054 case IVL_VT_REAL:
1055 datatype_flag = "/real";
1056 break;
1057 default:
1058 break;
1061 for (iword = 0 ; iword < ivl_signal_array_count(sig); iword += 1) {
1063 unsigned word_count = ivl_signal_array_count(sig);
1064 unsigned dimensions = ivl_signal_dimensions(sig);
1065 struct vvp_nexus_data*nex_data;
1067 /* Connect the pin of the signal to something. */
1068 ivl_nexus_t nex = ivl_signal_nex(sig, iword);
1069 const char*driver = draw_net_input(nex);
1071 nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
1072 assert(nex_data);
1074 if (nex_data->net == 0) {
1075 int strength_aware_flag = 0;
1076 const char*vec8 = "";
1077 if (nex_data->flags&VVP_NEXUS_DATA_STR)
1078 strength_aware_flag = 1;
1079 if (nex_data->drivers_count > 1)
1080 vec8 = "8";
1081 if (strength_aware_flag)
1082 vec8 = "8";
1084 if (iword == 0 && dimensions > 0) {
1085 int last = ivl_signal_array_base(sig) + word_count-1;
1086 int first = ivl_signal_array_base(sig);
1087 fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
1088 sig, vvp_mangle_name(ivl_signal_basename(sig)),
1089 last, first);
1091 if (dimensions > 0) {
1092 /* If this is a word of an array, then use an
1093 array reference in place of the net name. */
1094 fprintf(vvp_out, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1095 " %u drivers%s\n",
1096 sig, iword, vec8, datatype_flag, sig,
1097 iword, msb, lsb, driver,
1098 nex_data->drivers_count,
1099 strength_aware_flag?", strength-aware":"");
1100 } else {
1101 /* If this is an isolated word, it uses its
1102 own name. */
1103 assert(word_count == 1);
1104 fprintf(vvp_out, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
1105 " %u drivers%s\n",
1106 sig, iword, vec8, datatype_flag, local_flag,
1107 vvp_mangle_name(ivl_signal_basename(sig)),
1108 msb, lsb, driver,
1109 nex_data->drivers_count,
1110 strength_aware_flag?", strength-aware":"");
1112 nex_data->net = sig;
1113 nex_data->net_word = iword;
1115 } else if (dimensions > 0) {
1117 /* In this case, we have an alias to an existing
1118 signal array. this typically is an instance of
1119 port collapsing that the elaborator combined to
1120 discover that the entire array can be collapsed,
1121 so the word count for the signal and the alias
1122 *must* match. */
1124 if (word_count == ivl_signal_array_count(nex_data->net)) {
1125 if (iword == 0) {
1126 fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
1127 sig, vvp_mangle_name(ivl_signal_basename(sig)),
1128 nex_data->net,
1129 ivl_signal_basename(nex_data->net));
1131 /* An alias for an individual word. */
1132 } else {
1133 if (iword == 0) {
1134 int first = ivl_signal_array_base(sig);
1135 int last = first + word_count-1;
1136 fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
1137 sig,
1138 vvp_mangle_name(ivl_signal_basename(sig)),
1139 last, first);
1142 fprintf(vvp_out, "v%p_%u .alias%s v%p %u, %d %d, "
1143 "v%p_%u; Alias to %s\n", sig, iword,
1144 datatype_flag, sig, iword, msb, lsb,
1145 nex_data->net, nex_data->net_word,
1146 ivl_signal_basename(nex_data->net));
1148 } else {
1149 /* Finally, we may have an alias that is a word
1150 connected to another word. Again, this is a
1151 case of port collapsing. */
1153 /* For the alias, create a different kind of node
1154 that refers to the alias source data instead of
1155 holding our own data. */
1156 fprintf(vvp_out, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1157 sig, iword, datatype_flag,
1158 vvp_mangle_name(ivl_signal_basename(sig)),
1159 msb, lsb, nex_data->net, nex_data->net_word);
1164 static void draw_delay(ivl_net_logic_t lptr)
1166 ivl_expr_t d0 = ivl_logic_delay(lptr, 0);
1167 ivl_expr_t d1 = ivl_logic_delay(lptr, 1);
1168 ivl_expr_t d2 = ivl_logic_delay(lptr, 2);
1170 if (d0 == 0 && d1 == 0 && d2 == 0)
1171 return;
1173 /* FIXME: Assume that the expression is a constant */
1174 assert(number_is_immediate(d0, 64));
1175 assert(number_is_immediate(d1, 64));
1176 assert(number_is_immediate(d2, 64));
1178 if (d0 == d1 && d1 == d2)
1179 fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
1180 else
1181 fprintf(vvp_out, " (%lu,%lu,%lu)",
1182 get_number_immediate(d0),
1183 get_number_immediate(d1),
1184 get_number_immediate(d2));
1187 static void draw_udp_def(ivl_udp_t udp)
1189 unsigned init;
1190 unsigned i;
1192 switch (ivl_udp_init(udp))
1194 case '0':
1195 init = 0;
1196 break;
1197 case '1':
1198 init = 1;
1199 break;
1200 default:
1201 init = 2;
1202 break;
1205 if (ivl_udp_sequ(udp))
1206 fprintf(vvp_out,
1207 "UDP_%s .udp/sequ \"%s\", %d, %d",
1208 vvp_mangle_id(ivl_udp_name(udp)),
1209 vvp_mangle_name(ivl_udp_name(udp)),
1210 ivl_udp_nin(udp),
1211 init );
1212 else
1213 fprintf(vvp_out,
1214 "UDP_%s .udp/comb \"%s\", %d",
1215 vvp_mangle_id(ivl_udp_name(udp)),
1216 vvp_mangle_name(ivl_udp_name(udp)),
1217 ivl_udp_nin(udp));
1219 for (i=0; i<ivl_udp_rows(udp); i++)
1220 fprintf(vvp_out, "\n ,\"%s\"", ivl_udp_row(udp, i) );
1222 fprintf(vvp_out, ";\n");
1225 static void draw_udp_in_scope(ivl_net_logic_t lptr)
1227 unsigned pdx;
1229 ivl_udp_t udp = ivl_logic_udp(lptr);
1231 static ivl_udp_t *udps = 0x0;
1232 static int nudps = 0;
1233 int i;
1235 for (i=0; i<nudps; i++)
1236 if (udps[i] == udp)
1237 break;
1239 if (i >= nudps)
1241 udps = realloc(udps, (nudps+1)*sizeof(ivl_udp_t));
1242 assert(udps);
1243 udps[nudps++] = udp;
1244 draw_udp_def(udp);
1247 fprintf(vvp_out, "L_%p .udp", lptr);
1248 fprintf(vvp_out, " UDP_%s",
1249 vvp_mangle_id(ivl_udp_name(udp)));
1250 draw_delay(lptr);
1252 for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
1253 ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
1255 /* Unlike other logic gates, primitives may have unconnected
1256 inputs. The proper behavior is to attach a HiZ to the
1257 port. */
1258 if (nex == 0) {
1259 assert(ivl_logic_width(lptr) == 1);
1260 fprintf(vvp_out, ", C4<z>");
1262 } else {
1263 fprintf(vvp_out, ", %s", draw_net_input(nex));
1267 fprintf(vvp_out, ";\n");
1270 static void draw_logic_in_scope(ivl_net_logic_t lptr)
1272 unsigned pdx;
1273 const char*ltype = "?";
1274 const char*lcasc = 0;
1275 char identity_val = '0';
1277 int need_delay_flag = ivl_logic_delay(lptr,0)? 1 : 0;
1279 unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0));
1281 ivl_drive_t str0, str1;
1283 int level;
1284 int ninp = ivl_logic_pins(lptr) - 1;
1285 typedef const char*const_charp;
1286 const_charp*input_strings = calloc(ninp, sizeof(const_charp));
1288 for (pdx = 0 ; pdx < ninp ; pdx += 1) {
1289 ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
1290 if (nex == 0) {
1291 /* Only UDPs can have unconnected inputs. */
1292 assert(ivl_logic_type(lptr) == IVL_LO_UDP);
1293 input_strings[pdx] = 0;
1294 } else {
1295 input_strings[pdx] = draw_net_input(nex);
1299 switch (ivl_logic_type(lptr)) {
1301 case IVL_LO_UDP:
1302 free(input_strings);
1303 draw_udp_in_scope(lptr);
1304 return;
1306 case IVL_LO_BUFZ: {
1307 /* Draw bufz objects, but only if the gate cannot
1308 be elided. If I can elide it, then the
1309 draw_nex_input will take care of it for me. */
1310 ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0);
1312 ltype = "BUFZ";
1314 if (can_elide_bufz(lptr, nptr))
1315 return;
1317 break;
1320 case IVL_LO_PULLDOWN:
1321 case IVL_LO_PULLUP:
1322 /* Skip pullup and pulldown objects. Things that have
1323 pull objects as inputs will instead generate the
1324 appropriate C<?> symbol. */
1325 free(input_strings);
1326 return;
1328 case IVL_LO_AND:
1329 ltype = "AND";
1330 identity_val = '1';
1331 break;
1333 case IVL_LO_BUF:
1334 ltype = "BUF";
1335 break;
1337 case IVL_LO_BUFIF0:
1338 ltype = "BUFIF0";
1339 break;
1341 case IVL_LO_BUFIF1:
1342 ltype = "BUFIF1";
1343 break;
1345 case IVL_LO_NAND:
1346 ltype = "NAND";
1347 lcasc = "AND";
1348 identity_val = '1';
1349 break;
1351 case IVL_LO_NOR:
1352 ltype = "NOR";
1353 lcasc = "OR";
1354 break;
1356 case IVL_LO_NOT:
1357 ltype = "NOT";
1358 break;
1360 case IVL_LO_OR:
1361 ltype = "OR";
1362 break;
1364 case IVL_LO_XNOR:
1365 ltype = "XNOR";
1366 lcasc = "XOR";
1367 break;
1369 case IVL_LO_XOR:
1370 ltype = "XOR";
1371 break;
1373 case IVL_LO_CMOS:
1374 ltype = "CMOS";
1375 break;
1377 case IVL_LO_PMOS:
1378 ltype = "PMOS";
1379 break;
1381 case IVL_LO_NMOS:
1382 ltype = "NMOS";
1383 break;
1385 case IVL_LO_RCMOS:
1386 ltype = "RCMOS";
1387 break;
1389 case IVL_LO_RPMOS:
1390 ltype = "RPMOS";
1391 break;
1393 case IVL_LO_RNMOS:
1394 ltype = "RNMOS";
1395 break;
1397 case IVL_LO_NOTIF0:
1398 ltype = "NOTIF0";
1399 break;
1401 case IVL_LO_NOTIF1:
1402 ltype = "NOTIF1";
1403 break;
1405 default:
1406 fprintf(stderr, "vvp.tgt: error: Unhandled logic type: %u\n",
1407 ivl_logic_type(lptr));
1408 ltype = "?";
1409 break;
1412 { ivl_nexus_t nex = ivl_logic_pin(lptr, 0);
1413 ivl_nexus_ptr_t nptr = 0;
1414 unsigned idx;
1415 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
1416 nptr = ivl_nexus_ptr(nex,idx);
1417 if (ivl_nexus_ptr_log(nptr) != lptr)
1418 continue;
1419 if (ivl_nexus_ptr_pin(nptr) != 0)
1420 continue;
1421 break;
1423 str0 = ivl_nexus_ptr_drive0(nptr);
1424 str1 = ivl_nexus_ptr_drive1(nptr);
1427 if (!lcasc)
1428 lcasc = ltype;
1430 /* Get all the input label that I will use for parameters to
1431 the functor that I create later. */
1432 ninp = ivl_logic_pins(lptr) - 1;
1433 input_strings = calloc(ninp, sizeof(char*));
1434 for (pdx = 0 ; pdx < ninp ; pdx += 1)
1435 input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
1437 level = 0;
1438 ninp = ivl_logic_pins(lptr) - 1;
1439 while (ninp) {
1440 int inst;
1441 for (inst = 0; inst < ninp; inst += 4) {
1442 if (ninp > 4)
1443 fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
1444 lptr, level, inst, lcasc, vector_width);
1445 else {
1446 fprintf(vvp_out, "L_%p%s .functor %s %u",
1447 lptr, need_delay_flag? "/d" : "",
1448 ltype, vector_width);
1450 if (str0 != IVL_DR_STRONG || str1 != IVL_DR_STRONG)
1451 fprintf(vvp_out, " [%u %u]", str0, str1);
1454 for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) {
1455 if (level) {
1456 fprintf(vvp_out, ", L_%p/%d/%d",
1457 lptr, level - 1, pdx*4);
1458 } else {
1459 fprintf(vvp_out, ", %s", input_strings[pdx]);
1462 for ( ; pdx < inst+4 ; pdx += 1) {
1463 unsigned wdx;
1464 fprintf(vvp_out, ", C4<");
1465 for (wdx = 0 ; wdx < vector_width ; wdx += 1)
1466 fprintf(vvp_out, "%c", identity_val);
1467 fprintf(vvp_out, ">");
1470 fprintf(vvp_out, ";\n");
1472 if (ninp > 4)
1473 ninp = (ninp+3) / 4;
1474 else
1475 ninp = 0;
1476 level += 1;
1479 /* Free the array of char*. The strings themselves are
1480 persistent, held by the ivl_nexus_t objects. */
1481 free(input_strings);
1483 /* If there are delays, then draw the delay functor to carry
1484 that delay. This is the final output. */
1485 if (need_delay_flag) {
1486 ivl_expr_t rise_exp = ivl_logic_delay(lptr,0);
1487 ivl_expr_t fall_exp = ivl_logic_delay(lptr,1);
1488 ivl_expr_t decay_exp = ivl_logic_delay(lptr,2);
1490 if (number_is_immediate(rise_exp,64)
1491 && number_is_immediate(fall_exp,64)
1492 && number_is_immediate(decay_exp,64)) {
1494 fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1495 lptr, get_number_immediate(rise_exp),
1496 get_number_immediate(rise_exp),
1497 get_number_immediate(rise_exp), lptr);
1498 } else {
1499 ivl_signal_t sig;
1500 assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
1501 assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
1502 assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
1504 fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr);
1506 sig = ivl_expr_signal(rise_exp);
1507 assert(ivl_signal_array_count(sig) == 1);
1508 fprintf(vvp_out, ", v%p_0", sig);
1510 sig = ivl_expr_signal(fall_exp);
1511 assert(ivl_signal_array_count(sig) == 1);
1512 fprintf(vvp_out, ", v%p_0", sig);
1514 sig = ivl_expr_signal(decay_exp);
1515 assert(ivl_signal_array_count(sig) == 1);
1516 fprintf(vvp_out, ", v%p_0;\n", sig);
1521 static void draw_event_in_scope(ivl_event_t obj)
1523 unsigned nany = ivl_event_nany(obj);
1524 unsigned nneg = ivl_event_nneg(obj);
1525 unsigned npos = ivl_event_npos(obj);
1527 unsigned cnt = 0;
1529 /* Figure out how many probe functors are needed. */
1530 if (nany > 0)
1531 cnt += (nany+3) / 4;
1533 if (nneg > 0)
1534 cnt += (nneg+3) / 4;
1536 if (npos > 0)
1537 cnt += (npos+3) / 4;
1539 if (cnt == 0) {
1540 /* If none are needed, then this is a named event. The
1541 code needed is easy. */
1542 fprintf(vvp_out, "E_%p .event \"%s\";\n", obj,
1543 vvp_mangle_name(ivl_event_basename(obj)));
1545 } else if (cnt > 1) {
1546 /* There are a bunch of events that need to be event/or
1547 combined. */
1548 unsigned idx;
1549 unsigned ecnt = 0;
1551 for (idx = 0 ; idx < nany ; idx += 4, ecnt += 1) {
1552 unsigned sub, top;
1554 fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
1556 top = idx + 4;
1557 if (nany < top)
1558 top = nany;
1559 for (sub = idx ; sub < top ; sub += 1) {
1560 ivl_nexus_t nex = ivl_event_any(obj, sub);
1561 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1563 fprintf(vvp_out, ";\n");
1566 for (idx = 0 ; idx < nneg ; idx += 4, ecnt += 1) {
1567 unsigned sub, top;
1569 fprintf(vvp_out, "E_%p/%u .event negedge", obj, ecnt);
1571 top = idx + 4;
1572 if (nneg < top)
1573 top = nneg;
1574 for (sub = idx ; sub < top ; sub += 1) {
1575 ivl_nexus_t nex = ivl_event_neg(obj, sub);
1576 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1578 fprintf(vvp_out, ";\n");
1581 for (idx = 0 ; idx < npos ; idx += 4, ecnt += 1) {
1582 unsigned sub, top;
1584 fprintf(vvp_out, "E_%p/%u .event posedge", obj, ecnt);
1586 top = idx + 4;
1587 if (npos < top)
1588 top = npos;
1589 for (sub = idx ; sub < top ; sub += 1) {
1590 ivl_nexus_t nex = ivl_event_pos(obj, sub);
1591 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1593 fprintf(vvp_out, ";\n");
1596 assert(ecnt == cnt);
1598 fprintf(vvp_out, "E_%p .event/or", obj);
1599 fprintf(vvp_out, " E_%p/0", obj);
1601 for (idx = 1 ; idx < cnt ; idx += 1)
1602 fprintf(vvp_out, ", E_%p/%u", obj, idx);
1604 fprintf(vvp_out, ";\n");
1606 } else {
1607 unsigned num_input_strings = nany + nneg + npos;
1608 unsigned idx;
1609 ivl_nexus_t input_nexa[4];
1610 const char*edge = 0;
1612 assert(num_input_strings <= 4);
1614 if (nany > 0) {
1615 assert((nneg + npos) == 0);
1616 assert(nany <= 4);
1618 edge = "edge";
1620 for (idx = 0 ; idx < nany ; idx += 1) {
1621 ivl_nexus_t nex = ivl_event_any(obj, idx);
1622 input_nexa[idx] = nex;
1625 } else if (nneg > 0) {
1626 assert((nany + npos) == 0);
1627 edge = "negedge";
1629 for (idx = 0 ; idx < nneg ; idx += 1) {
1630 ivl_nexus_t nex = ivl_event_neg(obj, idx);
1631 input_nexa[idx] = nex;
1634 } else {
1635 assert((nany + nneg) == 0);
1636 edge = "posedge";
1638 for (idx = 0 ; idx < npos ; idx += 1) {
1639 ivl_nexus_t nex = ivl_event_pos(obj, idx);
1640 input_nexa[idx] = nex;
1644 fprintf(vvp_out, "E_%p .event %s", obj, edge);
1645 for (idx = 0 ; idx < num_input_strings ; idx += 1)
1646 fprintf(vvp_out, ", %s", draw_input_from_net(input_nexa[idx]));
1648 fprintf(vvp_out, ";\n");
1653 * This function draws any functors needed to calculate the input to
1654 * this nexus, and leaves in the data array strings that can be used
1655 * as functor arguments. The strings are from the draw_net_input
1656 * function, which in turn returns nexus names, so the strings are
1657 * safe to pass around.
1659 static void draw_lpm_data_inputs(ivl_lpm_t net, unsigned base,
1660 unsigned ndata, const char**src_table)
1662 unsigned idx;
1663 for (idx = 0 ; idx < ndata ; idx += 1) {
1664 ivl_nexus_t nex = ivl_lpm_data(net, base+idx);
1665 src_table[idx] = draw_net_input(nex);
1670 * If needed, draw a .delay node to delay the output from the LPM
1671 * device. Return the "/d" string if we drew this .delay node, or the
1672 * "" string if the node was not needed. The caller uses that string
1673 * to modify labels that are generated.
1675 static const char* draw_lpm_output_delay(ivl_lpm_t net)
1677 ivl_expr_t d_rise = ivl_lpm_delay(net, 0);
1678 ivl_expr_t d_fall = ivl_lpm_delay(net, 1);
1679 ivl_expr_t d_decay = ivl_lpm_delay(net, 2);
1681 const char*dly = "";
1682 if (d_rise != 0) {
1683 assert(number_is_immediate(d_rise, 64));
1684 assert(number_is_immediate(d_fall, 64));
1685 assert(number_is_immediate(d_decay, 64));
1686 dly = "/d";
1687 fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1688 net, get_number_immediate(d_rise),
1689 get_number_immediate(d_rise),
1690 get_number_immediate(d_rise), net);
1693 return dly;
1696 static void draw_lpm_add(ivl_lpm_t net)
1698 const char*src_table[2];
1699 unsigned width;
1700 const char*type = "";
1701 ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
1702 ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
1703 ivl_variable_type_t dto = IVL_VT_LOGIC;
1705 if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
1706 dto = IVL_VT_REAL;
1708 width = ivl_lpm_width(net);
1710 switch (ivl_lpm_type(net)) {
1711 case IVL_LPM_ADD:
1712 if (dto == IVL_VT_REAL)
1713 type = "sum.r";
1714 else
1715 type = "sum";
1716 break;
1717 case IVL_LPM_SUB:
1718 if (dto == IVL_VT_REAL)
1719 type = "sub.r";
1720 else
1721 type = "sub";
1722 break;
1723 case IVL_LPM_MULT:
1724 if (dto == IVL_VT_REAL)
1725 type = "mult.r";
1726 else
1727 type = "mult";
1728 break;
1729 case IVL_LPM_DIVIDE:
1730 if (dto == IVL_VT_REAL)
1731 type = "div.r";
1732 else if (ivl_lpm_signed(net))
1733 type = "div.s";
1734 else
1735 type = "div";
1736 break;
1737 case IVL_LPM_MOD:
1738 if (dto == IVL_VT_REAL)
1739 type = "mod.r";
1740 else
1741 type = "mod";
1742 break;
1743 case IVL_LPM_POW:
1744 if (dto == IVL_VT_REAL)
1745 type = "pow.r";
1746 else if (ivl_lpm_signed(net)) {
1747 type = "pow.s";
1748 if (width > 8*sizeof(long)) {
1749 fprintf(stderr, "%s:%u: sorry (vvp-tgt): Signed power "
1750 "result must be no more than %zu bits.\n",
1751 ivl_lpm_file(net), ivl_lpm_lineno(net),
1752 8*sizeof(long));
1753 exit(1);
1755 } else
1756 type = "pow";
1757 break;
1758 default:
1759 assert(0);
1762 draw_lpm_data_inputs(net, 0, 2, src_table);
1764 const char*dly = draw_lpm_output_delay(net);
1766 fprintf(vvp_out, "L_%p%s .arith/%s %u, %s, %s;\n",
1767 net, dly, type, width, src_table[0], src_table[1]);
1771 * The read port to an array is generated as a single record that takes
1772 * the address as an input.
1774 static void draw_lpm_array(ivl_lpm_t net)
1776 ivl_nexus_t nex;
1777 ivl_signal_t mem = ivl_lpm_array(net);
1779 fprintf(vvp_out, "L_%p .array/port v%p, ", net, mem);
1781 nex = ivl_lpm_select(net);
1782 fprintf(vvp_out, "%s", draw_net_input(nex));
1784 fprintf(vvp_out, ";\n");
1787 static void draw_lpm_cmp(ivl_lpm_t net)
1789 const char*src_table[2];
1790 unsigned width;
1791 const char*type = "";
1792 const char*signed_string = ivl_lpm_signed(net)? ".s" : "";
1793 ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
1794 ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
1795 ivl_variable_type_t dtc = IVL_VT_LOGIC;
1797 if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL)
1798 dtc = IVL_VT_REAL;
1800 width = ivl_lpm_width(net);
1802 switch (ivl_lpm_type(net)) {
1803 case IVL_LPM_CMP_EEQ:
1804 assert(dtc != IVL_VT_REAL); /* Should never get here! */
1805 type = "eeq";
1806 signed_string = "";
1807 break;
1808 case IVL_LPM_CMP_EQ:
1809 if (dtc == IVL_VT_REAL)
1810 type = "eq.r";
1811 else
1812 type = "eq";
1813 signed_string = "";
1814 break;
1815 case IVL_LPM_CMP_GE:
1816 if (dtc == IVL_VT_REAL) {
1817 type = "ge.r";
1818 signed_string = "";
1819 } else
1820 type = "ge";
1821 break;
1822 case IVL_LPM_CMP_GT:
1823 if (dtc == IVL_VT_REAL) {
1824 type = "gt.r";
1825 signed_string = "";
1826 } else
1827 type = "gt";
1828 break;
1829 case IVL_LPM_CMP_NE:
1830 if (dtc == IVL_VT_REAL)
1831 type = "ne.r";
1832 else
1833 type = "ne";
1834 signed_string = "";
1835 break;
1836 case IVL_LPM_CMP_NEE:
1837 assert(dtc != IVL_VT_REAL); /* Should never get here! */
1838 type = "nee";
1839 signed_string = "";
1840 break;
1841 default:
1842 assert(0);
1845 draw_lpm_data_inputs(net, 0, 2, src_table);
1847 const char*dly = draw_lpm_output_delay(net);
1849 fprintf(vvp_out, "L_%p%s .cmp/%s%s %u, %s, %s;\n",
1850 net, dly, type, signed_string, width,
1851 src_table[0], src_table[1]);
1855 * This function draws the arguments to a .const node using the
1856 * lpm inputs starting at "start" and for "cnt" inputs. This input
1857 * count must be <= 4. It is up to the caller to write the header part
1858 * of the statement, and to organize the data into multiple
1859 * statements.
1861 * Return the width of the final concatenation.
1863 static unsigned lpm_concat_inputs(ivl_lpm_t net, unsigned start,
1864 unsigned cnt, const char*src_table[])
1866 unsigned idx;
1867 unsigned wid = 0;
1869 assert(cnt <= 4);
1871 /* First, draw the [L M N O] part of the statement, the list
1872 of widths for the .concat statement. */
1873 fprintf(vvp_out, "[");
1875 for (idx = 0 ; idx < cnt ; idx += 1) {
1876 ivl_nexus_t nex = ivl_lpm_data(net, start+idx);
1877 unsigned nexus_width = width_of_nexus(nex);
1878 fprintf(vvp_out, " %u", nexus_width);
1879 wid += nexus_width;
1882 for ( ; idx < 4 ; idx += 1)
1883 fprintf(vvp_out, " 0");
1885 fprintf(vvp_out, "]");
1888 for (idx = 0 ; idx < cnt ; idx += 1) {
1889 fprintf(vvp_out, ", %s", src_table[idx]);
1892 fprintf(vvp_out, ";\n");
1893 return wid;
1897 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1898 * many nested nodes as necessary to support the desired number of
1899 * input vectors.
1901 static void draw_lpm_concat(ivl_lpm_t net)
1903 const char*src_table[4];
1904 unsigned icnt = ivl_lpm_selects(net);
1905 const char*dly = draw_lpm_output_delay(net);
1907 if (icnt <= 4) {
1908 /* This is the easiest case. There are 4 or fewer input
1909 vectors, so the entire IVL_LPM_CONCAT can be
1910 implemented with a single .concat node. */
1911 draw_lpm_data_inputs(net, 0, icnt, src_table);
1912 fprintf(vvp_out, "L_%p%s .concat ", net, dly);
1913 lpm_concat_inputs(net, 0, icnt, src_table);
1915 } else {
1916 /* If there are more than 4 inputs, things get more
1917 complicated. We need to generate a balanced tree of
1918 .concat nodes to blend the inputs down to a single
1919 root node, that becomes the output from the
1920 concatenation. */
1921 unsigned idx, depth;
1922 struct concat_tree {
1923 unsigned base;
1924 unsigned wid;
1925 } *tree;
1927 tree = malloc((icnt + 3)/4 * sizeof(struct concat_tree));
1929 /* First, fill in all the leaves with the initial inputs
1930 to the tree. After this loop, there are (icnt+3)/4
1931 .concat nodes drawn, that together take all the
1932 inputs. */
1933 for (idx = 0 ; idx < icnt ; idx += 4) {
1934 unsigned wid = 0;
1935 unsigned trans = 4;
1936 if ((idx + trans) > icnt)
1937 trans = icnt - idx;
1939 draw_lpm_data_inputs(net, idx, trans, src_table);
1940 fprintf(vvp_out, "LS_%p_0_%u .concat ", net, idx);
1941 wid = lpm_concat_inputs(net, idx, trans, src_table);
1943 tree[idx/4].base = idx;
1944 tree[idx/4].wid = wid;
1947 /* icnt is the input count for the level. It is the
1948 number of .concats of the previous level that have to
1949 be concatenated at the current level. (This is not
1950 the same as the bit width.) */
1951 icnt = (icnt + 3)/4;
1953 /* Tree now has icnt nodes that are depth=0 concat nodes
1954 which take in the leaf inputs. The while loop below
1955 starts and ends with a tree of icnt nodes. Each time
1956 through, there are 1/4 the nodes we started
1957 with. Thus, we eventually get down to <=4 nodes, and
1958 that is when we fall out of the loop. */
1960 depth = 1;
1961 while (icnt > 4) {
1962 for (idx = 0 ; idx < icnt ; idx += 4) {
1963 unsigned tdx;
1964 unsigned wid = 0;
1965 unsigned trans = 4;
1966 if ((idx+trans) > icnt)
1967 trans = icnt - idx;
1969 fprintf(vvp_out, "LS_%p_%u_%u .concat [",
1970 net, depth, idx);
1972 for (tdx = 0 ; tdx < trans ; tdx += 1) {
1973 fprintf(vvp_out, " %u", tree[idx+tdx].wid);
1974 wid += tree[idx+tdx].wid;
1977 for ( ; tdx < 4 ; tdx += 1)
1978 fprintf(vvp_out, " 0");
1980 fprintf(vvp_out, "]");
1982 for (tdx = 0; tdx < trans ; tdx += 1) {
1983 fprintf(vvp_out, ", LS_%p_%u_%u", net,
1984 depth-1, tree[idx+tdx].base);
1987 fprintf(vvp_out, ";\n");
1988 tree[idx/4].base = idx;
1989 tree[idx/4].wid = wid;
1992 depth += 1;
1993 icnt = (icnt + 3)/4;
1996 /* Finally, draw the root node that takes in the final
1997 row of tree nodes and generates a single output. */
1998 fprintf(vvp_out, "L_%p%s .concat [", net, dly);
1999 for (idx = 0 ; idx < icnt ; idx += 1)
2000 fprintf(vvp_out, " %u", tree[idx].wid);
2001 for ( ; idx < 4 ; idx += 1)
2002 fprintf(vvp_out, " 0");
2003 fprintf(vvp_out, "]");
2005 for (idx = 0 ; idx < icnt ; idx += 1)
2006 fprintf(vvp_out, ", LS_%p_%u_%u",
2007 net, depth-1, tree[idx].base);
2009 fprintf(vvp_out, ";\n");
2010 free(tree);
2015 * primitive FD (q, clk, ce, d);
2016 * output q;
2017 * reg q;
2018 * input clk, ce, d;
2019 * table
2020 * // clk ce d r s q q+
2021 * r 1 0 0 0 : ? : 0;
2022 * r 1 1 0 0 : ? : 1;
2023 * f 1 ? 0 0 : ? : -;
2024 * ? 1 ? 0 0 : ? : -;
2025 * * 0 ? 0 0 : ? : -;
2026 * ? ? ? 1 ? : ? : 0;
2027 * ? ? ? 0 1 : ? : 1;
2028 * endtable
2029 * endprimitive
2031 static void draw_lpm_ff(ivl_lpm_t net)
2033 ivl_expr_t aset_expr = 0;
2034 const char*aset_bits = 0;
2036 ivl_nexus_t nex;
2037 unsigned width;
2039 width = ivl_lpm_width(net);
2041 aset_expr = ivl_lpm_aset_value(net);
2042 if (aset_expr) {
2043 assert(ivl_expr_width(aset_expr) == width);
2044 aset_bits = ivl_expr_bits(aset_expr);
2048 fprintf(vvp_out, "L_%p .dff ", net);
2050 nex = ivl_lpm_data(net,0);
2051 assert(nex);
2052 fprintf(vvp_out, "%s", draw_net_input(nex));
2054 nex = ivl_lpm_clk(net);
2055 assert(nex);
2056 fprintf(vvp_out, ", %s", draw_net_input(nex));
2058 nex = ivl_lpm_enable(net);
2059 if (nex) {
2060 fprintf(vvp_out, ", %s", draw_net_input(nex));
2061 } else {
2062 fprintf(vvp_out, ", C4<1>");
2065 /* Stub asynchronous input for now. */
2066 fprintf(vvp_out, ", C4<z>");
2068 fprintf(vvp_out, ";\n");
2071 static void draw_lpm_shiftl(ivl_lpm_t net)
2073 unsigned width = ivl_lpm_width(net);
2074 const char* signed_flag = ivl_lpm_signed(net)? "s" : "";
2075 const char*dly = draw_lpm_output_delay(net);
2077 if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
2078 fprintf(vvp_out, "L_%p%s .shift/r%s %u", net, dly, signed_flag,
2079 width);
2080 else
2081 fprintf(vvp_out, "L_%p%s .shift/l %u", net, dly, width);
2083 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 0)));
2085 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 1)));
2087 fprintf(vvp_out, ";\n");
2090 static void draw_type_string_of_nex(ivl_nexus_t nex)
2092 switch (data_type_of_nexus(nex)) {
2093 case IVL_VT_REAL:
2094 fprintf(vvp_out, "r");
2095 break;
2096 case IVL_VT_LOGIC:
2097 case IVL_VT_BOOL:
2098 fprintf(vvp_out, "v%d", width_of_nexus(nex));
2099 break;
2100 default:
2101 assert(0);
2102 break;
2106 static void draw_lpm_sfunc(ivl_lpm_t net)
2108 unsigned idx;
2110 const char*dly = draw_lpm_output_delay(net);
2112 fprintf(vvp_out, "L_%p%s .sfunc %u %u \"%s\"", net, dly,
2113 ivl_file_table_index(ivl_lpm_file(net)), ivl_lpm_lineno(net),
2114 ivl_lpm_string(net));
2116 /* Print the function type descriptor string. */
2117 fprintf(vvp_out, ", \"");
2119 draw_type_string_of_nex(ivl_lpm_q(net,0));
2121 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
2122 draw_type_string_of_nex(ivl_lpm_data(net,idx));
2124 fprintf(vvp_out, "\"");
2126 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
2127 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
2130 fprintf(vvp_out, ";\n");
2133 static void draw_lpm_ufunc(ivl_lpm_t net)
2135 unsigned idx;
2136 ivl_scope_t def = ivl_lpm_define(net);
2138 const char*dly = draw_lpm_output_delay(net);
2140 fprintf(vvp_out, "L_%p%s .ufunc TD_%s, %u", net, dly,
2141 vvp_mangle_id(ivl_scope_name(def)),
2142 ivl_lpm_width(net));
2144 /* Print all the net signals that connect to the input of the
2145 function. */
2146 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
2147 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, idx)));
2151 assert((ivl_lpm_size(net)+1) == ivl_scope_ports(def));
2153 /* Now print all the variables in the function scope that
2154 receive the input values given in the previous list. */
2155 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
2156 ivl_signal_t psig = ivl_scope_port(def, idx+1);
2158 if (idx == 0)
2159 fprintf(vvp_out, " (");
2160 else
2161 fprintf(vvp_out, ", ");
2163 assert(ivl_signal_array_count(psig) == 1);
2164 fprintf(vvp_out, "v%p_0", psig);
2167 fprintf(vvp_out, ")");
2169 /* Finally, print the reference to the signal from which the
2170 result is collected. */
2171 { ivl_signal_t psig = ivl_scope_port(def, 0);
2172 assert(ivl_lpm_width(net) == ivl_signal_width(psig));
2173 assert(ivl_signal_array_count(psig) == 1);
2175 fprintf(vvp_out, " v%p_0", psig);
2178 fprintf(vvp_out, ";\n");
2182 * Handle a PART SELECT device. This has a single input and output,
2183 * plus an optional extra input that is a non-constant base.
2185 static void draw_lpm_part(ivl_lpm_t net)
2187 unsigned width, base;
2188 ivl_nexus_t sel;
2190 const char*dly = draw_lpm_output_delay(net);
2192 width = ivl_lpm_width(net);
2193 base = ivl_lpm_base(net);
2194 sel = ivl_lpm_data(net,1);
2196 if (sel == 0) {
2197 fprintf(vvp_out, "L_%p%s .part %s",
2198 net, dly, draw_net_input(ivl_lpm_data(net, 0)));
2199 fprintf(vvp_out, ", %u, %u;\n", base, width);
2200 } else {
2201 fprintf(vvp_out, "L_%p%s .part/v %s",
2202 net, dly, draw_net_input(ivl_lpm_data(net,0)));
2203 fprintf(vvp_out, ", %s", draw_net_input(sel));
2204 fprintf(vvp_out, ", %u;\n", width);
2209 * Handle a PART SELECT PV device. Generate a .part/pv node that
2210 * includes the part input, and the geometry of the part.
2212 static void draw_lpm_part_pv(ivl_lpm_t net)
2214 unsigned width = ivl_lpm_width(net);
2215 unsigned base = ivl_lpm_base(net);
2216 unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0));
2218 fprintf(vvp_out, "L_%p .part/pv %s",
2219 net, draw_net_input(ivl_lpm_data(net, 0)));
2221 fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width);
2225 * Handle the drawing of a bi-directional part select. The two ports
2226 * are simultaneously input and output. A simple minded connect of the
2227 * input to the output causes a functor cycle which will lock into an
2228 * X value, so something special is needed.
2230 * NOTE: The inputs of the tran device at this point need to be from
2231 * all the drivers of the nexus *except* the tran itself. This
2232 * function will draw three labels that can be linked:
2234 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2235 * ivl_lpm_data, the tran acts like a forward part select in that
2236 * way.
2238 * The device creates these nodes:
2240 * - L_%p/i
2241 * This is the Q port of the tran resolved and padded to the maximum
2242 * width of the tran. The tran itself is not included in the
2243 * resolution of this port.
2245 * - L_%p/V
2246 * This is the Q and D parts resolved together, still without the tran
2247 * driving anything.
2249 * - L_%p/P
2250 * This is the /V node part-selected back to the dimensions of the Q
2251 * side.
2253 static void draw_lpm_part_bi(ivl_lpm_t net)
2255 unsigned width = ivl_lpm_width(net);
2256 unsigned base = ivl_lpm_base(net);
2257 unsigned signal_width = width_of_nexus(ivl_lpm_data(net,0));
2259 unsigned idx;
2260 ivl_nexus_t nex;
2261 ivl_nexus_ptr_t ptr = 0;
2263 char*p_str;
2264 char*v_str;
2266 /* It seems implausible that the two inputs of a tran will be
2267 connected together. So assert that this is so to simplify
2268 the code to look for the nexus_ptr_t objects. */
2269 assert(ivl_lpm_q(net,0) != ivl_lpm_data(net,0));
2271 nex = ivl_lpm_q(net,0);
2272 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
2273 ptr = ivl_nexus_ptr(nex, idx);
2274 if (ivl_nexus_ptr_lpm(ptr) == net)
2275 break;
2277 assert(ptr != 0);
2278 p_str = draw_net_input_x(nex, ptr, 0, 0);
2280 nex = ivl_lpm_data(net,0);
2281 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
2282 ptr = ivl_nexus_ptr(nex, idx);
2283 if (ivl_nexus_ptr_lpm(ptr) == net)
2284 break;
2286 v_str = draw_net_input_x(nex, ptr, OMIT_PART_BI_DATA, 0);
2288 /* Pad the part-sized input out to a common width...
2289 The /i label is the Q side of the tran, resolved except for
2290 the tran itself and padded (with z) to the larger width. */
2291 fprintf(vvp_out, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2292 net, p_str, base, width, signal_width);
2294 /* Resolve together the two halves of the tran...
2295 The /V label is the ports of the tran (now the same width)
2296 resolved together. Neither input to this resolver includes
2297 the tran itself. */
2298 fprintf(vvp_out, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2299 net, net, v_str);
2301 /* The full-width side is created by the tran device, all we
2302 have left to to is take a part select of that for the
2303 smaller output, and this becomes the part select output of
2304 the BI device. */
2305 fprintf(vvp_out, "L_%p/P .part L_%p/V, %u, %u;\n", net,
2306 net, base, width);
2308 free(p_str);
2309 free(v_str);
2313 * Draw unary reduction devices.
2315 static void draw_lpm_re(ivl_lpm_t net, const char*type)
2317 const char*dly = draw_lpm_output_delay(net);
2319 fprintf(vvp_out, "L_%p%s .reduce/%s %s;\n", net, dly,
2320 type, draw_net_input(ivl_lpm_data(net,0)));
2323 static void draw_lpm_repeat(ivl_lpm_t net)
2325 fprintf(vvp_out, "L_%p .repeat %u, %u, %s;\n", net,
2326 ivl_lpm_width(net), ivl_lpm_size(net),
2327 draw_net_input(ivl_lpm_data(net,0)));
2330 static void draw_lpm_sign_ext(ivl_lpm_t net)
2332 fprintf(vvp_out, "L_%p .extend/s %u, %s;\n",
2333 net, ivl_lpm_width(net),
2334 draw_net_input(ivl_lpm_data(net,0)));
2337 static void draw_lpm_in_scope(ivl_lpm_t net)
2339 switch (ivl_lpm_type(net)) {
2341 case IVL_LPM_ADD:
2342 case IVL_LPM_SUB:
2343 case IVL_LPM_MULT:
2344 case IVL_LPM_DIVIDE:
2345 case IVL_LPM_MOD:
2346 case IVL_LPM_POW:
2347 draw_lpm_add(net);
2348 return;
2350 case IVL_LPM_ARRAY:
2351 draw_lpm_array(net);
2352 return;
2354 case IVL_LPM_PART_BI:
2355 draw_lpm_part_bi(net);
2356 return;
2358 case IVL_LPM_PART_VP:
2359 draw_lpm_part(net);
2360 return;
2362 case IVL_LPM_PART_PV:
2363 draw_lpm_part_pv(net);
2364 return;
2366 case IVL_LPM_CONCAT:
2367 draw_lpm_concat(net);
2368 return;
2370 case IVL_LPM_FF:
2371 draw_lpm_ff(net);
2372 return;
2374 case IVL_LPM_CMP_EEQ:
2375 case IVL_LPM_CMP_EQ:
2376 case IVL_LPM_CMP_GE:
2377 case IVL_LPM_CMP_GT:
2378 case IVL_LPM_CMP_NE:
2379 case IVL_LPM_CMP_NEE:
2380 draw_lpm_cmp(net);
2381 return;
2383 case IVL_LPM_MUX:
2384 draw_lpm_mux(net);
2385 return;
2387 case IVL_LPM_RE_AND:
2388 draw_lpm_re(net, "and");
2389 return;
2390 case IVL_LPM_RE_OR:
2391 draw_lpm_re(net, "or");
2392 return;
2393 case IVL_LPM_RE_XOR:
2394 draw_lpm_re(net, "xor");
2395 return;
2396 case IVL_LPM_RE_NAND:
2397 draw_lpm_re(net, "nand");
2398 return;
2399 case IVL_LPM_RE_NOR:
2400 draw_lpm_re(net, "nor");
2401 return;
2402 case IVL_LPM_RE_XNOR:
2403 draw_lpm_re(net, "xnor");
2404 return;
2406 case IVL_LPM_REPEAT:
2407 draw_lpm_repeat(net);
2408 return;
2410 case IVL_LPM_SHIFTL:
2411 case IVL_LPM_SHIFTR:
2412 draw_lpm_shiftl(net);
2413 return;
2415 case IVL_LPM_SIGN_EXT:
2416 draw_lpm_sign_ext(net);
2417 return;
2419 case IVL_LPM_SFUNC:
2420 draw_lpm_sfunc(net);
2421 return;
2423 case IVL_LPM_UFUNC:
2424 draw_lpm_ufunc(net);
2425 return;
2427 default:
2428 fprintf(stderr, "XXXX LPM not supported: %s.%s\n",
2429 ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net));
2433 int draw_scope(ivl_scope_t net, ivl_scope_t parent)
2435 unsigned idx;
2436 const char *type;
2437 switch (ivl_scope_type(net)) {
2438 case IVL_SCT_MODULE: type = "module"; break;
2439 case IVL_SCT_FUNCTION: type = "function"; break;
2440 case IVL_SCT_TASK: type = "task"; break;
2441 case IVL_SCT_BEGIN: type = "begin"; break;
2442 case IVL_SCT_FORK: type = "fork"; break;
2443 case IVL_SCT_GENERATE: type = "generate"; break;
2444 default: type = "?"; assert(0);
2447 fprintf(vvp_out, "S_%p .scope %s, \"%s\" \"%s\" %d %d",
2448 net, type, vvp_mangle_name(ivl_scope_basename(net)),
2449 ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)),
2450 ivl_scope_lineno(net));
2452 if (parent) {
2453 fprintf(vvp_out, ", %d %d, S_%p;\n",
2454 ivl_file_table_index(ivl_scope_def_file(net)),
2455 ivl_scope_def_lineno(net), parent);
2456 } else {
2458 fprintf(vvp_out, ";\n");
2461 fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net),
2462 ivl_scope_time_precision(net));
2464 for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
2465 ivl_parameter_t par = ivl_scope_param(net, idx);
2466 ivl_expr_t pex = ivl_parameter_expr(par);
2467 switch (ivl_expr_type(pex)) {
2468 case IVL_EX_STRING:
2469 fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n",
2470 par, ivl_parameter_basename(par),
2471 ivl_file_table_index(ivl_parameter_file(par)),
2472 ivl_parameter_lineno(par),
2473 ivl_expr_string(pex));
2474 break;
2475 case IVL_EX_NUMBER:
2476 fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<",
2477 par, ivl_parameter_basename(par),
2478 ivl_file_table_index(ivl_parameter_file(par)),
2479 ivl_parameter_lineno(par),
2480 ivl_expr_signed(pex)? "+":"");
2481 { const char*bits = ivl_expr_bits(pex);
2482 unsigned nbits = ivl_expr_width(pex);
2483 unsigned bb;
2484 for (bb = 0 ; bb < nbits; bb += 1)
2485 fprintf(vvp_out, "%c", bits[nbits-bb-1]);
2487 fprintf(vvp_out, ">;\n");
2488 break;
2489 case IVL_EX_REALNUM:
2490 fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n",
2491 par, ivl_parameter_basename(par),
2492 ivl_file_table_index(ivl_parameter_file(par)),
2493 ivl_parameter_lineno(par),
2494 draw_Cr_to_string(ivl_expr_dvalue(pex)),
2495 ivl_expr_dvalue(pex));
2496 break;
2497 default:
2498 fprintf(vvp_out, "; parameter type %d unsupported\n",
2499 ivl_expr_type(pex));
2500 break;
2504 /* Scan the scope for logic devices. For each device, draw out
2505 a functor that connects pin 0 to the output, and the
2506 remaining pins to inputs. */
2508 for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) {
2509 ivl_net_logic_t lptr = ivl_scope_log(net, idx);
2510 draw_logic_in_scope(lptr);
2514 /* Scan the signals (reg and net) and draw the appropriate
2515 statements to make the signal function. */
2517 for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) {
2518 ivl_signal_t sig = ivl_scope_sig(net, idx);
2520 switch (ivl_signal_type(sig)) {
2521 case IVL_SIT_REG:
2522 draw_reg_in_scope(sig);
2523 break;
2524 default:
2525 draw_net_in_scope(sig);
2526 break;
2530 for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) {
2531 ivl_event_t event = ivl_scope_event(net, idx);
2532 draw_event_in_scope(event);
2535 for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) {
2536 ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
2537 draw_lpm_in_scope(lpm);
2540 if (ivl_scope_type(net) == IVL_SCT_TASK)
2541 draw_task_definition(net);
2543 if (ivl_scope_type(net) == IVL_SCT_FUNCTION)
2544 draw_func_definition(net);
2546 ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
2547 return 0;