Add support for text macros with arguments.
[iverilog.git] / tgt-vvp / vvp_scope.c
blob3f6012dc46a77c6366e9e575f0709388da9500c7
1 /*
2 * Copyright (c) 2001-2005 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: vvp_scope.c,v 1.160 2007/04/12 04:40:37 steve Exp $"
21 #endif
23 # include "vvp_priv.h"
24 #ifdef HAVE_MALLOC_H
25 # include <malloc.h>
26 #endif
27 # include <stdlib.h>
28 # include <string.h>
29 # include <inttypes.h>
30 # include <assert.h>
32 struct vvp_nexus_data {
33 /* draw_net_input uses this */
34 const char*net_input;
35 unsigned drivers_count;
36 int flags;
37 /* draw_net_in_scope uses these to identify the controlling word. */
38 ivl_signal_t net;
39 unsigned net_word;
41 #define VVP_NEXUS_DATA_STR 0x0001
44 static struct vvp_nexus_data*new_nexus_data()
46 struct vvp_nexus_data*data = calloc(1, sizeof(struct vvp_nexus_data));
47 return data;
51 * Escape non-symbol characters in ids, and quotes in strings.
54 inline static char hex_digit(unsigned i)
56 i &= 0xf;
57 return i>=10 ? i-10+'A' : i+'0';
60 const char *vvp_mangle_id(const char *id)
62 static char *out = 0x0;
63 static size_t out_len;
65 int nesc = 0;
66 int iout = 0;
67 const char *inp = id;
69 const char nosym[] = "!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~";
71 char *se = strpbrk(inp, nosym);
72 if (!se)
73 return id;
75 do {
76 int n = se - inp;
77 unsigned int nlen = strlen(id) + 4*(++nesc) + 1;
78 if (out_len < nlen) {
79 out = realloc(out, nlen);
80 assert(out);
81 out_len = nlen;
83 if (n) {
84 strncpy(out+iout, inp, n);
85 iout += n;
87 inp += n+1;
88 out[iout++] = '\\';
89 switch (*se) {
90 case '\\':
91 case '/':
92 case '<':
93 case '>':
94 out[iout++] = *se;
95 break;
96 default:
97 out[iout++] = 'x';
98 out[iout++] = hex_digit(*se >> 4);
99 out[iout++] = hex_digit(*se);
100 break;
103 se = strpbrk(inp, nosym);
104 } while (se);
106 strcpy(out+iout, inp);
107 return out;
110 const char *vvp_mangle_name(const char *id)
112 static char *out = 0x0;
113 static size_t out_len;
115 int nesc = 0;
116 int iout = 0;
117 const char *inp = id;
119 const char nosym[] = "\"\\";
121 char *se = strpbrk(inp, nosym);
122 if (!se)
123 return id;
125 do {
126 int n = se - inp;
127 unsigned int nlen = strlen(id) + 2*(++nesc) + 1;
128 if (out_len < nlen) {
129 out = realloc(out, nlen);
130 assert(out);
131 out_len = nlen;
133 if (n) {
134 strncpy(out+iout, inp, n);
135 iout += n;
137 inp += n+1;
138 out[iout++] = '\\';
139 out[iout++] = *se;
141 se = strpbrk(inp, nosym);
142 } while (se);
144 strcpy(out+iout, inp);
145 return out;
148 static void draw_C4_repeated_constant(char bit_char, unsigned width)
150 unsigned idx;
152 fprintf(vvp_out, "C4<");
153 for (idx = 0 ; idx < width ; idx += 1)
154 fprintf(vvp_out, "%c", bit_char);
156 fprintf(vvp_out, ">");
159 static void str_repeat(char*buf, const char*str, unsigned rpt)
161 unsigned idx;
162 size_t len = strlen(str);
163 for (idx = 0 ; idx < rpt ; idx += 1) {
164 strcpy(buf, str);
165 buf += len;
169 /* REMOVE ME: vvp_signal_label should not be used. DEAD CODE
170 * Given a signal, generate a string name that is suitable for use as
171 * a label. The only rule is that the same signal will always have the
172 * same label. The result is stored in static memory, so remember to
173 * copy it out.
175 const char* vvp_signal_label(ivl_signal_t sig)
177 static char buf[32];
178 sprintf(buf, "%p", sig);
179 return buf;
182 ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word)
184 unsigned idx;
185 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
186 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
187 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
188 if (sig == 0)
189 continue;
190 if (ivl_signal_local(sig))
191 continue;
192 *word = ivl_nexus_ptr_pin(ptr);
193 return sig;
196 return 0;
199 ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex)
201 unsigned idx;
202 ivl_signal_type_t out = IVL_SIT_TRI;
204 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
205 ivl_signal_type_t stype;
206 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
207 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
208 if (sig == 0)
209 continue;
211 stype = ivl_signal_type(sig);
212 if (stype == IVL_SIT_REG)
213 continue;
214 if (stype == IVL_SIT_TRI)
215 continue;
216 if (stype == IVL_SIT_NONE)
217 continue;
218 out = stype;
221 return out;
224 unsigned width_of_nexus(ivl_nexus_t nex)
226 unsigned idx;
228 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
229 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
230 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
231 if (sig != 0)
232 return ivl_signal_width(sig);
235 return 0;
238 ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex)
240 unsigned idx;
241 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
242 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
243 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
244 if (sig != 0)
245 return ivl_signal_data_type(sig);
248 /* shouldn't happen! */
249 return IVL_VT_NO_TYPE;
253 ivl_nexus_ptr_t ivl_logic_pin_ptr(ivl_net_logic_t net, unsigned pin)
255 ivl_nexus_t nex = ivl_logic_pin(net, pin);
256 unsigned idx;
258 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
259 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
260 ivl_net_logic_t tmp = ivl_nexus_ptr_log(ptr);
261 if (tmp == 0)
262 continue;
263 if (tmp != net)
264 continue;
265 if (ivl_nexus_ptr_pin(ptr) != pin)
266 continue;
268 return ptr;
270 assert(0);
271 return 0;
274 const char*drive_string(ivl_drive_t drive)
276 switch (drive) {
277 case IVL_DR_HiZ:
278 return "";
279 case IVL_DR_SMALL:
280 return "sm";
281 case IVL_DR_MEDIUM:
282 return "me";
283 case IVL_DR_WEAK:
284 return "we";
285 case IVL_DR_LARGE:
286 return "la";
287 case IVL_DR_PULL:
288 return "pu";
289 case IVL_DR_STRONG:
290 return "";
291 case IVL_DR_SUPPLY:
292 return "su";
295 return "";
300 * The draw_scope function draws the major functional items within a
301 * scope. This includes the scopes themselves, of course. All the
302 * other functions in this file are in support of that task.
307 * NEXUS
308 * ivl builds up the netlist into objects connected together by
309 * ivl_nexus_t objects. The nexus receives all the drivers of the
310 * point in the net and resolves the value. The result is then sent to
311 * all the nets that are connected to the nexus. The nets, then, are
312 * read to get the value of the nexus.
314 * NETS
315 * Nets are interesting and special, because a nexus may be connected
316 * to several of them at once. This can happen, for example, as an
317 * artifact of module port connects, where the inside and the outside
318 * of the module are connected through an in-out port. (In fact, ivl
319 * will simply connect signals that are bound through a port, because
320 * the input/output/inout properties are enforced as compile time.)
322 * This case is handled by choosing one to receive the value of the
323 * nexus. This one then feeds to another net at the nexus, and so
324 * on. The last net is selected as the output of the nexus.
328 * This tests a bufz device against an output receiver, and determines
329 * if the device can be skipped. If this function returns true, then a
330 * gate will be generated for this node. Otherwise, the code generator
331 * will connect its input to its output and skip the gate.
333 static int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
335 ivl_nexus_t in_n;
336 unsigned idx;
338 /* These are the drives we expect. */
339 ivl_drive_t dr0 = ivl_nexus_ptr_drive0(nptr);
340 ivl_drive_t dr1 = ivl_nexus_ptr_drive1(nptr);
341 int drive_count = 0;
343 /* If the gate carries a delay, it must remain. */
344 if (ivl_logic_delay(net, 0) != 0)
345 return 0;
347 /* If the input is connected to the output, then do not elide
348 the gate. This is some sort of cycle. */
349 if (ivl_logic_pin(net, 0) == ivl_logic_pin(net, 1))
350 return 0;
352 in_n = ivl_logic_pin(net, 1);
353 for (idx = 0 ; idx < ivl_nexus_ptrs(in_n) ; idx += 1) {
354 ivl_nexus_ptr_t in_np = ivl_nexus_ptr(in_n, idx);
355 if (ivl_nexus_ptr_log(in_np) == net)
356 continue;
358 /* If the driver for the source does not match the
359 expected drive, then we need to keep the bufz. This
360 test also catches the case that the input device is
361 really also an input, as that device will have a
362 drive of HiZ. We need to keep BUFZ devices in that
363 case in order to prevent back-flow of data. */
364 if (ivl_nexus_ptr_drive0(in_np) != dr0)
365 return 0;
366 if (ivl_nexus_ptr_drive1(in_np) != dr1)
367 return 0;
369 drive_count += 1;
372 /* If the BUFZ input has multiple drivers on its input, then
373 we need to keep this device in order to hide the
374 resolution. */
375 if (drive_count != 1)
376 return 0;
378 return 1;
382 * Given a nexus, look for a signal that has module delay
383 * paths. Return that signal. (There should be no more than 1.) If we
384 * don't find any, then return nil.
386 static ivl_signal_t find_modpath(ivl_nexus_t nex)
388 unsigned idx;
389 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
390 ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx);
391 ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
392 if (sig == 0)
393 continue;
394 if (ivl_signal_npath(sig) == 0)
395 continue;
397 return sig;
400 return 0;
403 static char* draw_C4_to_string(ivl_net_const_t cptr)
405 const char*bits = ivl_const_bits(cptr);
406 unsigned idx;
408 size_t result_len = 5 + ivl_const_width(cptr);
409 char*result = malloc(result_len);
410 char*dp = result;
411 strcpy(dp, "C4<");
412 dp += strlen(dp);
414 for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
415 char bitchar = bits[ivl_const_width(cptr)-idx-1];
416 *dp++ = bitchar;
417 assert((dp - result) < result_len);
420 strcpy(dp, ">");
421 return result;
424 static char* draw_C8_to_string(ivl_net_const_t cptr,
425 ivl_drive_t dr0, ivl_drive_t dr1)
427 size_t nresult = 5 + 3*ivl_const_width(cptr);
428 char*result = malloc(nresult);
429 const char*bits = ivl_const_bits(cptr);
430 unsigned idx;
432 char dr0c = "01234567"[dr0];
433 char dr1c = "01234567"[dr1];
434 char*dp = result;
436 strcpy(dp, "C8<");
437 dp += strlen(dp);
439 for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) {
440 switch (bits[ivl_const_width(cptr)-idx-1]) {
441 case '0':
442 *dp++ = dr0c;
443 *dp++ = dr0c;
444 *dp++ = '0';
445 break;
446 case '1':
447 *dp++ = dr1c;
448 *dp++ = dr1c;
449 *dp++ = '1';
450 break;
451 case 'x':
452 case 'X':
453 *dp++ = dr0c;
454 *dp++ = dr1c;
455 *dp++ = 'x';
456 break;
457 case 'z':
458 case 'Z':
459 *dp++ = '0';
460 *dp++ = '0';
461 *dp++ = 'z';
462 break;
463 default:
464 assert(0);
465 break;
467 assert(dp - result < nresult);
470 strcpy(dp, ">");
471 return result;
475 * This function takes a nexus and looks for an input functor. It then
476 * draws to the output a string that represents that functor. What we
477 * are trying to do here is find the input to the net that is attached
478 * to this nexus.
481 static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
483 unsigned nptr_pin = ivl_nexus_ptr_pin(nptr);
484 ivl_net_const_t cptr;
485 ivl_net_logic_t lptr;
486 ivl_signal_t sptr;
487 ivl_lpm_t lpm;
489 lptr = ivl_nexus_ptr_log(nptr);
490 if (lptr && (ivl_logic_type(lptr) == IVL_LO_BUFZ) && (nptr_pin == 0))
491 do {
492 if (! can_elide_bufz(lptr, nptr))
493 break;
495 return strdup(draw_net_input(ivl_logic_pin(lptr, 1)));
496 } while(0);
498 /* If this is a pulldown device, then there is a single pin
499 that drives a constant value to the entire width of the
500 vector. The driver normally drives a pull0 value, so a C8<>
501 constant is appropriate, but if the drive is really strong,
502 then we can draw a C4<> constant instead. */
503 if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) {
504 if (ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) {
505 size_t result_len = ivl_logic_width(lptr) + 5;
506 char*result = malloc(result_len);
507 char*dp = result;
508 strcpy(dp, "C4<");
509 dp += strlen(dp);
510 str_repeat(dp, "0", ivl_logic_width(lptr));
511 dp += ivl_logic_width(lptr);
512 *dp++ = '>';
513 *dp = 0;
514 assert((dp-result) <= result_len);
515 return result;
516 } else {
517 char val[4];
518 size_t result_len = 3*ivl_logic_width(lptr) + 5;
519 char*result = malloc(result_len);
520 char*dp = result;
522 val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
523 val[1] = val[0];
524 val[2] = '0';
525 val[3] = 0;
527 strcpy(dp, "C8<");
528 dp += strlen(dp);
529 str_repeat(dp, val, ivl_logic_width(lptr));
530 dp += 3*ivl_logic_width(lptr);
531 *dp++ = '>';
532 *dp = 0;
533 assert((dp-result) <= result_len);
534 return result;
538 if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) {
539 if (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG) {
540 size_t result_len = 5 + ivl_logic_width(lptr);
541 char*result = malloc(result_len);
542 char*dp = result;
543 strcpy(dp, "C4<");
544 dp += strlen(dp);
545 str_repeat(dp, "1", ivl_logic_width(lptr));
546 dp += ivl_logic_width(lptr);
547 *dp++ = '>';
548 *dp = 0;
549 assert((dp-result) <= result_len);
550 return result;
551 } else {
552 char val[4];
553 size_t result_len = 5 + 3*ivl_logic_width(lptr);
554 char*result = malloc(result_len);
555 char*dp = result;
557 val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)];
558 val[1] = val[0];
559 val[2] = '1';
560 val[3] = 0;
562 strcpy(dp, "C8<");
563 dp += strlen(dp);
564 str_repeat(dp, val, ivl_logic_width(lptr));
565 dp += 3*ivl_logic_width(lptr);
566 *dp++ = '>';
567 *dp = 0;
568 assert((dp-result) <= result_len);
569 return result;
573 if (lptr && (nptr_pin == 0)) {
574 char tmp[128];
575 snprintf(tmp, sizeof tmp, "L_%p", lptr);
576 return strdup(tmp);
579 sptr = ivl_nexus_ptr_sig(nptr);
580 if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
581 char tmp[128];
582 /* Input is a .var. This device may be a non-zero pin
583 because it may be an array of reg vectors. */
584 snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin);
585 return strdup(tmp);
588 cptr = ivl_nexus_ptr_con(nptr);
589 if (cptr) {
590 /* Constants should have exactly 1 pin, with a literal value. */
591 assert(nptr_pin == 0);
592 char *result = 0;
594 switch (ivl_const_type(cptr)) {
595 case IVL_VT_LOGIC:
596 case IVL_VT_BOOL:
597 if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG)
598 && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) {
600 result = draw_C4_to_string(cptr);
602 } else {
603 result = draw_C8_to_string(cptr,
604 ivl_nexus_ptr_drive0(nptr),
605 ivl_nexus_ptr_drive1(nptr));
607 break;
609 case IVL_VT_REAL:
610 { char tmp[256];
611 snprintf(tmp, sizeof(tmp),
612 "Cr<%lg>", ivl_const_real(cptr));
613 result = strdup(tmp);
615 break;
617 default:
618 assert(0);
619 break;
622 return result;
625 lpm = ivl_nexus_ptr_lpm(nptr);
626 if (lpm) switch (ivl_lpm_type(lpm)) {
628 case IVL_LPM_FF:
629 case IVL_LPM_ADD:
630 case IVL_LPM_ARRAY:
631 case IVL_LPM_CONCAT:
632 case IVL_LPM_CMP_EEQ:
633 case IVL_LPM_CMP_EQ:
634 case IVL_LPM_CMP_GE:
635 case IVL_LPM_CMP_GT:
636 case IVL_LPM_CMP_NE:
637 case IVL_LPM_CMP_NEE:
638 case IVL_LPM_RE_AND:
639 case IVL_LPM_RE_OR:
640 case IVL_LPM_RE_XOR:
641 case IVL_LPM_RE_NAND:
642 case IVL_LPM_RE_NOR:
643 case IVL_LPM_RE_XNOR:
644 case IVL_LPM_SFUNC:
645 case IVL_LPM_SHIFTL:
646 case IVL_LPM_SHIFTR:
647 case IVL_LPM_SIGN_EXT:
648 case IVL_LPM_SUB:
649 case IVL_LPM_MULT:
650 case IVL_LPM_MUX:
651 case IVL_LPM_DIVIDE:
652 case IVL_LPM_MOD:
653 case IVL_LPM_UFUNC:
654 case IVL_LPM_PART_VP:
655 case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */
656 case IVL_LPM_REPEAT:
657 if (ivl_lpm_q(lpm, 0) == nex) {
658 char tmp[128];
659 snprintf(tmp, sizeof tmp, "L_%p", lpm);
660 return strdup(tmp);
662 break;
664 case IVL_LPM_PART_BI:
665 if (ivl_lpm_q(lpm, 0) == nex) {
666 char tmp[128];
667 snprintf(tmp, sizeof tmp, "L_%p/P", lpm);
668 return strdup(tmp);
669 } else if (ivl_lpm_data(lpm,0) == nex) {
670 char tmp[128];
671 snprintf(tmp, sizeof tmp, "L_%p/V", lpm);
672 return strdup(tmp);
674 break;
677 fprintf(stderr, "internal error: no input to nexus %s\n",
678 ivl_nexus_name(nex));
679 assert(0);
680 return strdup("C<z>");
683 static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr)
685 if (ivl_nexus_ptr_drive0(nptr) != IVL_DR_STRONG)
686 return 1;
687 if (ivl_nexus_ptr_drive1(nptr) != IVL_DR_STRONG)
688 return 1;
690 ivl_net_logic_t log = ivl_nexus_ptr_log(nptr);
691 if (log != 0) {
692 /* These logic gates are able to generate unusual
693 strength values and so their outputs are considered
694 strength aware. */
695 if (ivl_logic_type(log) == IVL_LO_BUFIF0)
696 return 1;
697 if (ivl_logic_type(log) == IVL_LO_BUFIF1)
698 return 1;
699 if (ivl_logic_type(log) == IVL_LO_PMOS)
700 return 1;
701 if (ivl_logic_type(log) == IVL_LO_NMOS)
702 return 1;
703 if (ivl_logic_type(log) == IVL_LO_CMOS)
704 return 1;
707 return 0;
711 * This function draws the input to a net into a string. What that
712 * means is that it returns a static string that can be used to
713 * represent a resolved driver to a nexus. If there are multiple
714 * drivers to the nexus, then it writes out the resolver declarations
715 * needed to perform strength resolution.
717 * The string that this returns is malloced, and that means that the
718 * caller must free the string or store it permanently. This function
719 * does *not* check for a previously calculated string. Use the
720 * draw_net_input for the general case.
722 /* Omit LPMPART_BI device pin-data(0) drivers. */
723 # define OMIT_PART_BI_DATA 0x0001
725 static char* draw_net_input_x(ivl_nexus_t nex,
726 ivl_nexus_ptr_t omit_ptr, int omit_flags,
727 struct vvp_nexus_data*nex_data)
729 ivl_signal_type_t res;
730 char result[512];
731 unsigned idx;
732 int level;
733 unsigned ndrivers = 0;
734 static ivl_nexus_ptr_t *drivers = 0x0;
735 static unsigned adrivers = 0;
737 const char*resolv_type;
739 char*nex_private = 0;
741 /* Accumulate nex_data flags. */
742 int nex_flags = 0;
744 res = signal_type_of_nexus(nex);
745 switch (res) {
746 case IVL_SIT_TRI:
747 resolv_type = "tri";
748 break;
749 case IVL_SIT_TRI0:
750 resolv_type = "tri0";
751 nex_flags |= VVP_NEXUS_DATA_STR;
752 break;
753 case IVL_SIT_TRI1:
754 resolv_type = "tri1";
755 nex_flags |= VVP_NEXUS_DATA_STR;
756 break;
757 case IVL_SIT_TRIAND:
758 resolv_type = "triand";
759 break;
760 case IVL_SIT_TRIOR:
761 resolv_type = "trior";
762 break;
763 default:
764 fprintf(stderr, "vvp.tgt: Unsupported signal type: %u\n", res);
765 assert(0);
766 resolv_type = "tri";
767 break;
771 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
772 ivl_lpm_t lpm_tmp;
773 ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, idx);
775 /* If we are supposed to skip LPM_PART_BI data pins,
776 check that this driver is that. */
777 if ((omit_flags&OMIT_PART_BI_DATA)
778 && (lpm_tmp = ivl_nexus_ptr_lpm(nptr))
779 && (nex == ivl_lpm_data(lpm_tmp,0)))
780 continue;
782 if (nptr == omit_ptr)
783 continue;
785 /* Skip input only pins. */
786 if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_HiZ)
787 && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_HiZ))
788 continue;
790 /* Mark the strength-aware flag if the driver can
791 generate values other than the standard "6"
792 strength. */
793 if (nexus_drive_is_strength_aware(nptr))
794 nex_flags |= VVP_NEXUS_DATA_STR;
796 /* Save this driver. */
797 if (ndrivers >= adrivers) {
798 adrivers += 4;
799 drivers = realloc(drivers, adrivers*sizeof(ivl_nexus_ptr_t));
800 assert(drivers);
802 drivers[ndrivers] = nptr;
803 ndrivers += 1;
806 /* If the caller is collecting nexus information, then save
807 the nexus driver count in the nex_data. */
808 if (nex_data) {
809 nex_data->drivers_count = ndrivers;
810 nex_data->flags |= nex_flags;
813 /* If the nexus has no drivers, then send a constant HiZ into
814 the net. */
815 if (ndrivers == 0) {
816 unsigned idx, wid = width_of_nexus(nex);
817 char*tmp = malloc(wid + 5);
818 nex_private = tmp;
819 strcpy(tmp, "C4<");
820 tmp += strlen(tmp);
821 switch (res) {
822 case IVL_SIT_TRI:
823 for (idx = 0 ; idx < wid ; idx += 1)
824 *tmp++ = 'z';
825 break;
826 case IVL_SIT_TRI0:
827 for (idx = 0 ; idx < wid ; idx += 1)
828 *tmp++ = '0';
829 break;
830 case IVL_SIT_TRI1:
831 for (idx = 0 ; idx < wid ; idx += 1)
832 *tmp++ = '1';
833 break;
834 default:
835 assert(0);
837 *tmp++ = '>';
838 *tmp = 0;
839 return nex_private;
843 /* If the nexus has exactly one driver, then simply draw
844 it. Note that this will *not* work if the nexus is not a
845 TRI type nexus. */
846 if (ndrivers == 1 && res == IVL_SIT_TRI) {
847 ivl_signal_t path_sig = find_modpath(nex);
848 if (path_sig) {
849 char*nex_str = draw_net_input_drive(nex, drivers[0]);
850 char modpath_label[64];
851 snprintf(modpath_label, sizeof modpath_label,
852 "V_%p/m", path_sig);
853 nex_private = strdup(modpath_label);
854 draw_modpath(path_sig, nex_str);
856 } else {
857 nex_private = draw_net_input_drive(nex, drivers[0]);
859 return nex_private;
862 level = 0;
863 while (ndrivers) {
864 unsigned int inst;
865 for (inst = 0; inst < ndrivers; inst += 4) {
866 if (ndrivers > 4)
867 fprintf(vvp_out, "RS_%p/%d/%d .resolv tri",
868 nex, level, inst);
869 else
870 fprintf(vvp_out, "RS_%p .resolv %s",
871 nex, resolv_type);
873 for (idx = inst; idx < ndrivers && idx < inst+4; idx += 1) {
874 if (level) {
875 fprintf(vvp_out, ", RS_%p/%d/%d",
876 nex, level - 1, idx*4);
877 } else {
878 char*drive = draw_net_input_drive(nex, drivers[idx]);
879 fprintf(vvp_out, ", %s", drive);
880 free(drive);
883 for ( ; idx < inst+4 ; idx += 1) {
884 fprintf(vvp_out, ", ");
885 draw_C4_repeated_constant('z',width_of_nexus(nex));
888 fprintf(vvp_out, ";\n");
890 if (ndrivers > 4)
891 ndrivers = (ndrivers+3) / 4;
892 else
893 ndrivers = 0;
894 level += 1;
897 sprintf(result, "RS_%p", nex);
898 nex_private = strdup(result);
899 return nex_private;
903 * Get a cached description of the nexus input, or create one if this
904 * nexus has not been cached yet. This is a wrapper for the common
905 * case call to draw_net_input_x.
907 const char*draw_net_input(ivl_nexus_t nex)
909 struct vvp_nexus_data*nex_data = (struct vvp_nexus_data*)
910 ivl_nexus_get_private(nex);
912 /* If this nexus already has a label, then its input is
913 already figured out. Just return the existing label. */
914 if (nex_data && nex_data->net_input)
915 return nex_data->net_input;
917 if (nex_data == 0) {
918 nex_data = new_nexus_data();
919 ivl_nexus_set_private(nex, nex_data);
922 assert(nex_data->net_input == 0);
923 nex_data->net_input = draw_net_input_x(nex, 0, 0, nex_data);
925 return nex_data->net_input;
928 const char*draw_input_from_net(ivl_nexus_t nex)
930 static char result[32];
931 unsigned word;
933 ivl_signal_t sig = signal_of_nexus(nex, &word);
934 if (sig == 0)
935 return draw_net_input(nex);
937 snprintf(result, sizeof result, "v%p_%u", sig, word);
938 return result;
943 * This function draws a reg/int/variable in the scope. This is a very
944 * simple device to draw as there are no inputs to connect so no need
945 * to scan the nexus. We do have to account for the possibility that
946 * the device is arrayed, though, by making a node for each array element.
948 static void draw_reg_in_scope(ivl_signal_t sig)
950 int msb = ivl_signal_msb(sig);
951 int lsb = ivl_signal_lsb(sig);
953 const char*datatype_flag = ivl_signal_integer(sig) ? "/i" :
954 ivl_signal_signed(sig)? "/s" : "";
956 switch (ivl_signal_data_type(sig)) {
957 case IVL_VT_REAL:
958 datatype_flag = "/real";
959 break;
960 default:
961 break;
964 /* If the reg objects are collected into an array, then first
965 write out the .array record to declare the array indices. */
966 if (ivl_signal_dimensions(sig) > 0) {
967 unsigned word_count = ivl_signal_array_count(sig);
968 int last = ivl_signal_array_base(sig)+word_count-1;
969 int first = ivl_signal_array_base(sig);
970 fprintf(vvp_out, "v%p .array%s \"%s\", %d %d, %d %d;\n",
971 sig, datatype_flag,
972 vvp_mangle_name(ivl_signal_basename(sig)),
973 last, first, msb, lsb);
975 } else {
977 fprintf(vvp_out, "v%p_0 .var%s \"%s\", %d %d;\n",
978 sig, datatype_flag,
979 vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
985 * This function draws a net. This is a bit more complicated as we
986 * have to find an appropriate functor to connect to the input.
988 static void draw_net_in_scope(ivl_signal_t sig)
990 int msb = ivl_signal_msb(sig);
991 int lsb = ivl_signal_lsb(sig);
993 const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
994 unsigned iword;
996 /* Skip the local signal. */
997 if (ivl_signal_local(sig))
998 return;
1000 switch (ivl_signal_data_type(sig)) {
1001 case IVL_VT_REAL:
1002 datatype_flag = "/real";
1003 break;
1004 default:
1005 break;
1008 for (iword = 0 ; iword < ivl_signal_array_count(sig); iword += 1) {
1010 unsigned word_count = ivl_signal_array_count(sig);
1011 unsigned dimensions = ivl_signal_dimensions(sig);
1012 struct vvp_nexus_data*nex_data;
1014 /* Connect the pin of the signal to something. */
1015 ivl_nexus_t nex = ivl_signal_nex(sig, iword);
1016 const char*driver = draw_net_input(nex);
1018 nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
1019 assert(nex_data);
1021 if (nex_data->net == 0) {
1022 int strength_aware_flag = 0;
1023 const char*vec8 = "";
1024 if (nex_data->flags&VVP_NEXUS_DATA_STR)
1025 strength_aware_flag = 1;
1026 if (nex_data->drivers_count > 1)
1027 vec8 = "8";
1028 if (strength_aware_flag)
1029 vec8 = "8";
1031 if (iword == 0 && dimensions > 0) {
1032 int last = ivl_signal_array_base(sig) + word_count-1;
1033 int first = ivl_signal_array_base(sig);
1034 fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
1035 sig, vvp_mangle_name(ivl_signal_basename(sig)),
1036 last, first);
1038 if (dimensions > 0) {
1039 /* If this is a word of an array, then use an
1040 array reference in place of the net name. */
1041 fprintf(vvp_out, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1042 " %u drivers%s\n",
1043 sig, iword, vec8, datatype_flag, sig,
1044 iword, msb, lsb, driver,
1045 nex_data->drivers_count,
1046 strength_aware_flag?", strength-aware":"");
1047 } else {
1048 /* If this is an isolated word, it uses its
1049 own name. */
1050 assert(word_count == 1);
1051 fprintf(vvp_out, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
1052 " %u drivers%s\n",
1053 sig, iword, vec8, datatype_flag,
1054 vvp_mangle_name(ivl_signal_basename(sig)),
1055 msb, lsb, driver,
1056 nex_data->drivers_count,
1057 strength_aware_flag?", strength-aware":"");
1059 nex_data->net = sig;
1060 nex_data->net_word = iword;
1062 } else if (dimensions > 0) {
1064 /* In this case, we have an alias to an existing
1065 signal array. this typically is an instance of
1066 port collapsing that the elaborator combined to
1067 discover that the entire array can be collapsed,
1068 so the word count for the signal and the alias
1069 *must* match. */
1070 assert(word_count == ivl_signal_array_count(nex_data->net));
1072 if (iword == 0) {
1073 fprintf(vvp_out, "v%p .array \"%s\", v%p; Alias to %s\n",
1074 sig, vvp_mangle_name(ivl_signal_basename(sig)),
1075 nex_data->net, ivl_signal_basename(nex_data->net));
1077 /* An alias for the individual words? */
1078 #if 0
1079 fprintf(vvp_out, "v%p_%u .alias%s v%p, %d %d, v%p_%u;\n",
1080 sig, iword, datatype_flag, sig,
1081 msb, lsb, nex_data->net, nex_data->net_word);
1082 #endif
1083 } else {
1084 /* Finally, we may have an alias that is a word
1085 connected to another word. Again, this is a
1086 case of port collapsing. */
1088 /* For the alias, create a different kind of node
1089 that refers to the alias source data instead of
1090 holding our own data. */
1091 fprintf(vvp_out, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1092 sig, iword, datatype_flag,
1093 vvp_mangle_name(ivl_signal_basename(sig)),
1094 msb, lsb, nex_data->net, nex_data->net_word);
1099 static void draw_delay(ivl_net_logic_t lptr)
1101 ivl_expr_t d0 = ivl_logic_delay(lptr, 0);
1102 ivl_expr_t d1 = ivl_logic_delay(lptr, 1);
1103 ivl_expr_t d2 = ivl_logic_delay(lptr, 2);
1105 if (d0 == 0 && d1 == 0 && d2 == 0)
1106 return;
1108 /* FIXME: Assume that the expression is a constant */
1109 assert(number_is_immediate(d0, 64));
1110 assert(number_is_immediate(d1, 64));
1111 assert(number_is_immediate(d2, 64));
1113 if (d0 == d1 && d1 == d2)
1114 fprintf(vvp_out, " (%lu)", get_number_immediate(d0));
1115 else
1116 fprintf(vvp_out, " (%lu,%lu,%lu)",
1117 get_number_immediate(d0),
1118 get_number_immediate(d1),
1119 get_number_immediate(d2));
1122 static void draw_udp_def(ivl_udp_t udp)
1124 unsigned init;
1125 unsigned i;
1127 switch (ivl_udp_init(udp))
1129 case '0':
1130 init = 0;
1131 break;
1132 case '1':
1133 init = 1;
1134 break;
1135 default:
1136 init = 2;
1137 break;
1140 if (ivl_udp_sequ(udp))
1141 fprintf(vvp_out,
1142 "UDP_%s .udp/sequ \"%s\", %d, %d",
1143 vvp_mangle_id(ivl_udp_name(udp)),
1144 vvp_mangle_name(ivl_udp_name(udp)),
1145 ivl_udp_nin(udp),
1146 init );
1147 else
1148 fprintf(vvp_out,
1149 "UDP_%s .udp/comb \"%s\", %d",
1150 vvp_mangle_id(ivl_udp_name(udp)),
1151 vvp_mangle_name(ivl_udp_name(udp)),
1152 ivl_udp_nin(udp));
1154 for (i=0; i<ivl_udp_rows(udp); i++)
1155 fprintf(vvp_out, "\n ,\"%s\"", ivl_udp_row(udp, i) );
1157 fprintf(vvp_out, ";\n");
1160 static void draw_udp_in_scope(ivl_net_logic_t lptr)
1162 unsigned pdx;
1164 ivl_udp_t udp = ivl_logic_udp(lptr);
1166 static ivl_udp_t *udps = 0x0;
1167 static int nudps = 0;
1168 int i;
1170 for (i=0; i<nudps; i++)
1171 if (udps[i] == udp)
1172 break;
1174 if (i >= nudps)
1176 udps = realloc(udps, (nudps+1)*sizeof(ivl_udp_t));
1177 assert(udps);
1178 udps[nudps++] = udp;
1179 draw_udp_def(udp);
1182 fprintf(vvp_out, "L_%p .udp", lptr);
1183 fprintf(vvp_out, " UDP_%s",
1184 vvp_mangle_id(ivl_udp_name(udp)));
1185 draw_delay(lptr);
1187 for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) {
1188 ivl_nexus_t nex = ivl_logic_pin(lptr, pdx);
1190 /* Unlike other logic gates, primitives may have unconnected
1191 inputs. The proper behavior is to attach a HiZ to the
1192 port. */
1193 if (nex == 0) {
1194 assert(ivl_logic_width(lptr) == 1);
1195 fprintf(vvp_out, ", C4<z>");
1197 } else {
1198 fprintf(vvp_out, ", %s", draw_net_input(nex));
1202 fprintf(vvp_out, ";\n");
1205 static void draw_logic_in_scope(ivl_net_logic_t lptr)
1207 unsigned pdx;
1208 const char*ltype = "?";
1209 const char*lcasc = 0;
1210 char identity_val = '0';
1212 int need_delay_flag = ivl_logic_delay(lptr,0)? 1 : 0;
1214 unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0));
1216 ivl_drive_t str0, str1;
1218 int level;
1219 int ninp = ivl_logic_pins(lptr) - 1;
1220 typedef const char*const_charp;
1221 const_charp*input_strings = calloc(ninp, sizeof(const_charp));
1223 for (pdx = 0 ; pdx < ninp ; pdx += 1) {
1224 ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1);
1225 if (nex == 0) {
1226 /* Only UDPs can have unconnected inputs. */
1227 assert(ivl_logic_type(lptr) == IVL_LO_UDP);
1228 input_strings[pdx] = 0;
1229 } else {
1230 input_strings[pdx] = draw_net_input(nex);
1234 switch (ivl_logic_type(lptr)) {
1236 case IVL_LO_UDP:
1237 free(input_strings);
1238 draw_udp_in_scope(lptr);
1239 return;
1241 case IVL_LO_BUFZ: {
1242 /* Draw bufz objects, but only if the gate cannot
1243 be elided. If I can elide it, then the
1244 draw_nex_input will take care of it for me. */
1245 ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0);
1247 ltype = "BUFZ";
1249 if (can_elide_bufz(lptr, nptr))
1250 return;
1252 break;
1255 case IVL_LO_PULLDOWN:
1256 case IVL_LO_PULLUP:
1257 /* Skip pullup and pulldown objects. Things that have
1258 pull objects as inputs will instead generate the
1259 appropriate C<?> symbol. */
1260 free(input_strings);
1261 return;
1263 case IVL_LO_AND:
1264 ltype = "AND";
1265 identity_val = '1';
1266 break;
1268 case IVL_LO_BUF:
1269 ltype = "BUF";
1270 break;
1272 case IVL_LO_BUFIF0:
1273 ltype = "BUFIF0";
1274 break;
1276 case IVL_LO_BUFIF1:
1277 ltype = "BUFIF1";
1278 break;
1280 case IVL_LO_NAND:
1281 ltype = "NAND";
1282 lcasc = "AND";
1283 identity_val = '1';
1284 break;
1286 case IVL_LO_NOR:
1287 ltype = "NOR";
1288 lcasc = "OR";
1289 break;
1291 case IVL_LO_NOT:
1292 ltype = "NOT";
1293 break;
1295 case IVL_LO_OR:
1296 ltype = "OR";
1297 break;
1299 case IVL_LO_XNOR:
1300 ltype = "XNOR";
1301 lcasc = "XOR";
1302 break;
1304 case IVL_LO_XOR:
1305 ltype = "XOR";
1306 break;
1308 case IVL_LO_CMOS:
1309 ltype = "CMOS";
1310 break;
1312 case IVL_LO_PMOS:
1313 ltype = "PMOS";
1314 break;
1316 case IVL_LO_NMOS:
1317 ltype = "NMOS";
1318 break;
1320 case IVL_LO_RCMOS:
1321 ltype = "RCMOS";
1322 break;
1324 case IVL_LO_RPMOS:
1325 ltype = "RPMOS";
1326 break;
1328 case IVL_LO_RNMOS:
1329 ltype = "RNMOS";
1330 break;
1332 case IVL_LO_NOTIF0:
1333 ltype = "NOTIF0";
1334 break;
1336 case IVL_LO_NOTIF1:
1337 ltype = "NOTIF1";
1338 break;
1340 default:
1341 fprintf(stderr, "vvp.tgt: error: Unhandled logic type: %u\n",
1342 ivl_logic_type(lptr));
1343 ltype = "?";
1344 break;
1347 { ivl_nexus_t nex = ivl_logic_pin(lptr, 0);
1348 ivl_nexus_ptr_t nptr = 0;
1349 unsigned idx;
1350 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
1351 nptr = ivl_nexus_ptr(nex,idx);
1352 if (ivl_nexus_ptr_log(nptr) != lptr)
1353 continue;
1354 if (ivl_nexus_ptr_pin(nptr) != 0)
1355 continue;
1356 break;
1358 str0 = ivl_nexus_ptr_drive0(nptr);
1359 str1 = ivl_nexus_ptr_drive1(nptr);
1362 if (!lcasc)
1363 lcasc = ltype;
1365 /* Get all the input label that I will use for parameters to
1366 the functor that I create later. */
1367 ninp = ivl_logic_pins(lptr) - 1;
1368 input_strings = calloc(ninp, sizeof(char*));
1369 for (pdx = 0 ; pdx < ninp ; pdx += 1)
1370 input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1));
1372 level = 0;
1373 ninp = ivl_logic_pins(lptr) - 1;
1374 while (ninp) {
1375 int inst;
1376 for (inst = 0; inst < ninp; inst += 4) {
1377 if (ninp > 4)
1378 fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
1379 lptr, level, inst, lcasc, vector_width);
1380 else {
1381 fprintf(vvp_out, "L_%p%s .functor %s %u",
1382 lptr, need_delay_flag? "/d" : "",
1383 ltype, vector_width);
1385 if (str0 != IVL_DR_STRONG || str1 != IVL_DR_STRONG)
1386 fprintf(vvp_out, " [%u %u]", str0, str1);
1389 for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) {
1390 if (level) {
1391 fprintf(vvp_out, ", L_%p/%d/%d",
1392 lptr, level - 1, pdx*4);
1393 } else {
1394 fprintf(vvp_out, ", %s", input_strings[pdx]);
1397 for ( ; pdx < inst+4 ; pdx += 1) {
1398 unsigned wdx;
1399 fprintf(vvp_out, ", C4<");
1400 for (wdx = 0 ; wdx < vector_width ; wdx += 1)
1401 fprintf(vvp_out, "%c", identity_val);
1402 fprintf(vvp_out, ">");
1405 fprintf(vvp_out, ";\n");
1407 if (ninp > 4)
1408 ninp = (ninp+3) / 4;
1409 else
1410 ninp = 0;
1411 level += 1;
1414 /* Free the array of char*. The strings themselves are
1415 persistent, held by the ivl_nexus_t objects. */
1416 free(input_strings);
1418 /* If there are delays, then draw the delay functor to carry
1419 that delay. This is the final output. */
1420 if (need_delay_flag) {
1421 ivl_expr_t rise_exp = ivl_logic_delay(lptr,0);
1422 ivl_expr_t fall_exp = ivl_logic_delay(lptr,1);
1423 ivl_expr_t decay_exp = ivl_logic_delay(lptr,2);
1425 if (number_is_immediate(rise_exp,64)
1426 && number_is_immediate(fall_exp,64)
1427 && number_is_immediate(decay_exp,64)) {
1429 fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1430 lptr, get_number_immediate(rise_exp),
1431 get_number_immediate(rise_exp),
1432 get_number_immediate(rise_exp), lptr);
1433 } else {
1434 ivl_signal_t sig;
1435 assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL);
1436 assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL);
1437 assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL);
1439 fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr);
1441 sig = ivl_expr_signal(rise_exp);
1442 assert(ivl_signal_array_count(sig) == 1);
1443 fprintf(vvp_out, ", v%p_0", sig);
1445 sig = ivl_expr_signal(fall_exp);
1446 assert(ivl_signal_array_count(sig) == 1);
1447 fprintf(vvp_out, ", v%p_0", sig);
1449 sig = ivl_expr_signal(decay_exp);
1450 assert(ivl_signal_array_count(sig) == 1);
1451 fprintf(vvp_out, ", v%p_0;\n", sig);
1456 static void draw_event_in_scope(ivl_event_t obj)
1458 unsigned nany = ivl_event_nany(obj);
1459 unsigned nneg = ivl_event_nneg(obj);
1460 unsigned npos = ivl_event_npos(obj);
1462 unsigned cnt = 0;
1464 /* Figure out how many probe functors are needed. */
1465 if (nany > 0)
1466 cnt += (nany+3) / 4;
1468 if (nneg > 0)
1469 cnt += (nneg+3) / 4;
1471 if (npos > 0)
1472 cnt += (npos+3) / 4;
1474 if (cnt == 0) {
1475 /* If none are needed, then this is a named event. The
1476 code needed is easy. */
1477 fprintf(vvp_out, "E_%p .event \"%s\";\n", obj,
1478 vvp_mangle_name(ivl_event_basename(obj)));
1480 } else if (cnt > 1) {
1481 /* There are a bunch of events that need to be event/or
1482 combined. */
1483 unsigned idx;
1484 unsigned ecnt = 0;
1486 for (idx = 0 ; idx < nany ; idx += 4, ecnt += 1) {
1487 unsigned sub, top;
1489 fprintf(vvp_out, "E_%p/%u .event edge", obj, ecnt);
1491 top = idx + 4;
1492 if (nany < top)
1493 top = nany;
1494 for (sub = idx ; sub < top ; sub += 1) {
1495 ivl_nexus_t nex = ivl_event_any(obj, sub);
1496 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1498 fprintf(vvp_out, ";\n");
1501 for (idx = 0 ; idx < nneg ; idx += 4, ecnt += 1) {
1502 unsigned sub, top;
1504 fprintf(vvp_out, "E_%p/%u .event negedge", obj, ecnt);
1506 top = idx + 4;
1507 if (nneg < top)
1508 top = nneg;
1509 for (sub = idx ; sub < top ; sub += 1) {
1510 ivl_nexus_t nex = ivl_event_neg(obj, sub);
1511 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1513 fprintf(vvp_out, ";\n");
1516 for (idx = 0 ; idx < npos ; idx += 4, ecnt += 1) {
1517 unsigned sub, top;
1519 fprintf(vvp_out, "E_%p/%u .event posedge", obj, ecnt);
1521 top = idx + 4;
1522 if (npos < top)
1523 top = npos;
1524 for (sub = idx ; sub < top ; sub += 1) {
1525 ivl_nexus_t nex = ivl_event_pos(obj, sub);
1526 fprintf(vvp_out, ", %s", draw_input_from_net(nex));
1528 fprintf(vvp_out, ";\n");
1531 assert(ecnt == cnt);
1533 fprintf(vvp_out, "E_%p .event/or", obj);
1534 fprintf(vvp_out, " E_%p/0", obj);
1536 for (idx = 1 ; idx < cnt ; idx += 1)
1537 fprintf(vvp_out, ", E_%p/%u", obj, idx);
1539 fprintf(vvp_out, ";\n");
1541 } else {
1542 unsigned num_input_strings = nany + nneg + npos;
1543 unsigned idx;
1544 ivl_nexus_t input_nexa[4];
1545 const char*edge = 0;
1547 assert(num_input_strings <= 4);
1549 if (nany > 0) {
1550 assert((nneg + npos) == 0);
1551 assert(nany <= 4);
1553 edge = "edge";
1555 for (idx = 0 ; idx < nany ; idx += 1) {
1556 ivl_nexus_t nex = ivl_event_any(obj, idx);
1557 input_nexa[idx] = nex;
1560 } else if (nneg > 0) {
1561 assert((nany + npos) == 0);
1562 edge = "negedge";
1564 for (idx = 0 ; idx < nneg ; idx += 1) {
1565 ivl_nexus_t nex = ivl_event_neg(obj, idx);
1566 input_nexa[idx] = nex;
1569 } else {
1570 assert((nany + nneg) == 0);
1571 edge = "posedge";
1573 for (idx = 0 ; idx < npos ; idx += 1) {
1574 ivl_nexus_t nex = ivl_event_pos(obj, idx);
1575 input_nexa[idx] = nex;
1579 fprintf(vvp_out, "E_%p .event %s", obj, edge);
1580 for (idx = 0 ; idx < num_input_strings ; idx += 1)
1581 fprintf(vvp_out, ", %s", draw_input_from_net(input_nexa[idx]));
1583 fprintf(vvp_out, ";\n");
1588 * This function draws any functors needed to calculate the input to
1589 * this nexus, and leaves in the data array strings that can be used
1590 * as functor arguments. The strings are from the draw_net_input
1591 * function, which in turn returns nexus names, so the strings are
1592 * safe to pass around.
1594 static void draw_lpm_data_inputs(ivl_lpm_t net, unsigned base,
1595 unsigned ndata, const char**src_table)
1597 unsigned idx;
1598 for (idx = 0 ; idx < ndata ; idx += 1) {
1599 ivl_nexus_t nex = ivl_lpm_data(net, base+idx);
1600 src_table[idx] = draw_net_input(nex);
1604 static void draw_lpm_add(ivl_lpm_t net)
1606 const char*src_table[2];
1607 unsigned width;
1608 const char*type = "";
1609 ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0));
1610 ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1));
1611 ivl_variable_type_t dto = IVL_VT_LOGIC;
1613 if (dta == IVL_VT_REAL && dtb == IVL_VT_REAL)
1614 dto = IVL_VT_REAL;
1616 width = ivl_lpm_width(net);
1618 switch (ivl_lpm_type(net)) {
1619 case IVL_LPM_ADD:
1620 type = "sum";
1621 break;
1622 case IVL_LPM_SUB:
1623 if (dto == IVL_VT_REAL)
1624 type = "sub.r";
1625 else
1626 type = "sub";
1627 break;
1628 case IVL_LPM_MULT:
1629 type = "mult";
1630 break;
1631 case IVL_LPM_DIVIDE:
1632 if (dto == IVL_VT_REAL)
1633 type = "div.r";
1634 else if (ivl_lpm_signed(net))
1635 type = "div.s";
1636 else
1637 type = "div";
1638 break;
1639 case IVL_LPM_MOD:
1640 type = "mod";
1641 break;
1642 default:
1643 assert(0);
1646 draw_lpm_data_inputs(net, 0, 2, src_table);
1647 fprintf(vvp_out, "L_%p .arith/%s %u, %s, %s;\n",
1648 net, type, width, src_table[0], src_table[1]);
1652 * The read port to an array is generated as a single record that takes
1653 * the address as an input.
1655 static void draw_lpm_array(ivl_lpm_t net)
1657 ivl_nexus_t nex;
1658 ivl_signal_t mem = ivl_lpm_array(net);
1660 fprintf(vvp_out, "L_%p .array/port v%p, ", net, mem);
1662 nex = ivl_lpm_select(net);
1663 fprintf(vvp_out, "%s", draw_net_input(nex));
1665 fprintf(vvp_out, ";\n");
1668 static void draw_lpm_cmp(ivl_lpm_t net)
1670 const char*src_table[2];
1671 unsigned width;
1672 const char*type = "";
1673 const char*signed_string = ivl_lpm_signed(net)? ".s" : "";
1675 width = ivl_lpm_width(net);
1677 switch (ivl_lpm_type(net)) {
1678 case IVL_LPM_CMP_EEQ:
1679 type = "eeq";
1680 signed_string = "";
1681 break;
1682 case IVL_LPM_CMP_EQ:
1683 type = "eq";
1684 signed_string = "";
1685 break;
1686 case IVL_LPM_CMP_GE:
1687 type = "ge";
1688 break;
1689 case IVL_LPM_CMP_GT:
1690 type = "gt";
1691 break;
1692 case IVL_LPM_CMP_NE:
1693 type = "ne";
1694 signed_string = "";
1695 break;
1696 case IVL_LPM_CMP_NEE:
1697 type = "nee";
1698 signed_string = "";
1699 break;
1700 default:
1701 assert(0);
1704 draw_lpm_data_inputs(net, 0, 2, src_table);
1705 fprintf(vvp_out, "L_%p .cmp/%s%s %u, %s, %s;\n",
1706 net, type, signed_string, width,
1707 src_table[0], src_table[1]);
1711 * This function draws the arguments to a .const node using the
1712 * lpm inputs starting at "start" and for "cnt" inputs. This input
1713 * count must be <= 4. It is up to the caller to write the header part
1714 * of the statement, and to organize the data into multiple
1715 * statements.
1717 * Return the width of the final concatenation.
1719 static unsigned lpm_concat_inputs(ivl_lpm_t net, unsigned start,
1720 unsigned cnt, const char*src_table[])
1722 unsigned idx;
1723 unsigned wid = 0;
1725 assert(cnt <= 4);
1727 /* First, draw the [L M N O] part of the statement, the list
1728 of widths for the .concat statement. */
1729 fprintf(vvp_out, "[");
1731 for (idx = 0 ; idx < cnt ; idx += 1) {
1732 ivl_nexus_t nex = ivl_lpm_data(net, start+idx);
1733 unsigned nexus_width = width_of_nexus(nex);
1734 fprintf(vvp_out, " %u", nexus_width);
1735 wid += nexus_width;
1738 for ( ; idx < 4 ; idx += 1)
1739 fprintf(vvp_out, " 0");
1741 fprintf(vvp_out, "]");
1744 for (idx = 0 ; idx < cnt ; idx += 1) {
1745 fprintf(vvp_out, ", %s", src_table[idx]);
1748 fprintf(vvp_out, ";\n");
1749 return wid;
1753 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1754 * many nested nodes as necessary to support the desired number of
1755 * input vectors.
1757 static void draw_lpm_concat(ivl_lpm_t net)
1759 const char*src_table[4];
1760 unsigned icnt = ivl_lpm_selects(net);
1762 if (icnt <= 4) {
1763 /* This is the easiest case. There are 4 or fewer input
1764 vectors, so the entire IVL_LPM_CONCAT can be
1765 implemented with a single .concat node. */
1766 draw_lpm_data_inputs(net, 0, icnt, src_table);
1767 fprintf(vvp_out, "L_%p .concat ", net);
1768 lpm_concat_inputs(net, 0, icnt, src_table);
1770 } else {
1771 /* If there are more than 4 inputs, things get more
1772 complicated. We need to generate a balanced tree of
1773 .concat nodes to blend the inputs down to a single
1774 root node, that becomes the output from the
1775 concatenation. */
1776 unsigned idx, depth;
1777 struct concat_tree {
1778 unsigned base;
1779 unsigned wid;
1780 } *tree;
1782 tree = malloc((icnt + 3)/4 * sizeof(struct concat_tree));
1784 /* First, fill in all the leaves with the initial inputs
1785 to the tree. After this loop, there are (icnt+3)/4
1786 .concat nodes drawn, that together take all the
1787 inputs. */
1788 for (idx = 0 ; idx < icnt ; idx += 4) {
1789 unsigned wid = 0;
1790 unsigned trans = 4;
1791 if ((idx + trans) > icnt)
1792 trans = icnt - idx;
1794 draw_lpm_data_inputs(net, idx, trans, src_table);
1795 fprintf(vvp_out, "LS_%p_0_%u .concat ", net, idx);
1796 wid = lpm_concat_inputs(net, idx, trans, src_table);
1798 tree[idx/4].base = idx;
1799 tree[idx/4].wid = wid;
1802 /* icnt is the input count for the level. It is the
1803 number of .concats of the previous level that have to
1804 be concatenated at the current level. (This is not
1805 the same as the bit width.) */
1806 icnt = (icnt + 3)/4;
1808 /* Tree now has icnt nodes that are depth=0 concat nodes
1809 which take in the leaf inputs. The while loop below
1810 starts and ends with a tree of icnt nodes. Each time
1811 through, there are 1/4 the nodes we started
1812 with. Thus, we eventually get down to <=4 nodes, and
1813 that is when we fall out of the loop. */
1815 depth = 1;
1816 while (icnt > 4) {
1817 for (idx = 0 ; idx < icnt ; idx += 4) {
1818 unsigned tdx;
1819 unsigned wid = 0;
1820 unsigned trans = 4;
1821 if ((idx+trans) > icnt)
1822 trans = icnt - idx;
1824 fprintf(vvp_out, "LS_%p_%u_%u .concat [",
1825 net, depth, idx);
1827 for (tdx = 0 ; tdx < trans ; tdx += 1) {
1828 fprintf(vvp_out, " %u", tree[idx+tdx].wid);
1829 wid += tree[idx+tdx].wid;
1832 for ( ; tdx < 4 ; tdx += 1)
1833 fprintf(vvp_out, " 0");
1835 fprintf(vvp_out, "]");
1837 for (tdx = 0; tdx < trans ; tdx += 1) {
1838 fprintf(vvp_out, ", LS_%p_%u_%u", net,
1839 depth-1, tree[idx+tdx].base);
1842 fprintf(vvp_out, ";\n");
1843 tree[idx/4].base = idx;
1844 tree[idx/4].wid = wid;
1847 depth += 1;
1848 icnt = (icnt + 3)/4;
1851 /* Finally, draw the root node that takes in the final
1852 row of tree nodes and generates a single output. */
1853 fprintf(vvp_out, "L_%p .concat [", net);
1854 for (idx = 0 ; idx < icnt ; idx += 1)
1855 fprintf(vvp_out, " %u", tree[idx].wid);
1856 for ( ; idx < 4 ; idx += 1)
1857 fprintf(vvp_out, " 0");
1858 fprintf(vvp_out, "]");
1860 for (idx = 0 ; idx < icnt ; idx += 1)
1861 fprintf(vvp_out, ", LS_%p_%u_%u",
1862 net, depth-1, tree[idx].base);
1864 fprintf(vvp_out, ";\n");
1865 free(tree);
1870 * primitive FD (q, clk, ce, d);
1871 * output q;
1872 * reg q;
1873 * input clk, ce, d;
1874 * table
1875 * // clk ce d r s q q+
1876 * r 1 0 0 0 : ? : 0;
1877 * r 1 1 0 0 : ? : 1;
1878 * f 1 ? 0 0 : ? : -;
1879 * ? 1 ? 0 0 : ? : -;
1880 * * 0 ? 0 0 : ? : -;
1881 * ? ? ? 1 ? : ? : 0;
1882 * ? ? ? 0 1 : ? : 1;
1883 * endtable
1884 * endprimitive
1886 static void draw_lpm_ff(ivl_lpm_t net)
1888 ivl_expr_t aset_expr = 0;
1889 const char*aset_bits = 0;
1891 ivl_nexus_t nex;
1892 unsigned width;
1894 width = ivl_lpm_width(net);
1896 aset_expr = ivl_lpm_aset_value(net);
1897 if (aset_expr) {
1898 assert(ivl_expr_width(aset_expr) == width);
1899 aset_bits = ivl_expr_bits(aset_expr);
1903 fprintf(vvp_out, "L_%p .dff ", net);
1905 nex = ivl_lpm_data(net,0);
1906 assert(nex);
1907 fprintf(vvp_out, "%s", draw_net_input(nex));
1909 nex = ivl_lpm_clk(net);
1910 assert(nex);
1911 fprintf(vvp_out, ", %s", draw_net_input(nex));
1913 nex = ivl_lpm_enable(net);
1914 if (nex) {
1915 fprintf(vvp_out, ", %s", draw_net_input(nex));
1916 } else {
1917 fprintf(vvp_out, ", C4<1>");
1920 /* Stub asynchronous input for now. */
1921 fprintf(vvp_out, ", C4<z>");
1923 fprintf(vvp_out, ";\n");
1926 static void draw_lpm_shiftl(ivl_lpm_t net)
1928 unsigned width = ivl_lpm_width(net);
1929 const char* signed_flag = ivl_lpm_signed(net)? "s" : "";
1931 if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
1932 fprintf(vvp_out, "L_%p .shift/r%s %u", net, signed_flag, width);
1933 else
1934 fprintf(vvp_out, "L_%p .shift/l %u", net, width);
1936 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 0)));
1938 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 1)));
1940 fprintf(vvp_out, ";\n");
1943 static void draw_type_string_of_nex(ivl_nexus_t nex)
1945 switch (data_type_of_nexus(nex)) {
1946 case IVL_VT_REAL:
1947 fprintf(vvp_out, "r");
1948 break;
1949 case IVL_VT_LOGIC:
1950 case IVL_VT_BOOL:
1951 fprintf(vvp_out, "v%d", width_of_nexus(nex));
1952 break;
1953 default:
1954 assert(0);
1955 break;
1959 static void draw_lpm_sfunc(ivl_lpm_t net)
1961 unsigned idx;
1962 fprintf(vvp_out, "L_%p .sfunc \"%s\"", net, ivl_lpm_string(net));
1964 /* Print the function type descriptor string. */
1965 fprintf(vvp_out, ", \"");
1967 draw_type_string_of_nex(ivl_lpm_q(net,0));
1969 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
1970 draw_type_string_of_nex(ivl_lpm_data(net,idx));
1972 fprintf(vvp_out, "\"");
1974 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
1975 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
1978 fprintf(vvp_out, ";\n");
1981 static void draw_lpm_ufunc(ivl_lpm_t net)
1983 unsigned idx;
1984 ivl_scope_t def = ivl_lpm_define(net);
1986 fprintf(vvp_out, "L_%p .ufunc TD_%s, %u", net,
1987 ivl_scope_name(def),
1988 ivl_lpm_width(net));
1990 /* Print all the net signals that connect to the input of the
1991 function. */
1992 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
1993 fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, idx)));
1997 assert((ivl_lpm_size(net)+1) == ivl_scope_ports(def));
1999 /* Now print all the variables in the function scope that
2000 receive the input values given in the previous list. */
2001 for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
2002 ivl_signal_t psig = ivl_scope_port(def, idx+1);
2004 if (idx == 0)
2005 fprintf(vvp_out, " (");
2006 else
2007 fprintf(vvp_out, ", ");
2009 assert(ivl_signal_array_count(psig) == 1);
2010 fprintf(vvp_out, "v%p_0", psig);
2013 fprintf(vvp_out, ")");
2015 /* Finally, print the reference to the signal from which the
2016 result is collected. */
2017 { ivl_signal_t psig = ivl_scope_port(def, 0);
2018 assert(ivl_lpm_width(net) == ivl_signal_width(psig));
2019 assert(ivl_signal_array_count(psig) == 1);
2021 fprintf(vvp_out, " v%p_0", psig);
2024 fprintf(vvp_out, ";\n");
2028 * Handle a PART SELECT device. This has a single input and output,
2029 * plus an optional extra input that is a non-constant base.
2031 static void draw_lpm_part(ivl_lpm_t net)
2033 unsigned width, base;
2034 ivl_nexus_t sel;
2036 width = ivl_lpm_width(net);
2037 base = ivl_lpm_base(net);
2038 sel = ivl_lpm_data(net,1);
2040 if (sel == 0) {
2041 fprintf(vvp_out, "L_%p .part %s",
2042 net, draw_net_input(ivl_lpm_data(net, 0)));
2043 fprintf(vvp_out, ", %u, %u;\n", base, width);
2044 } else {
2045 fprintf(vvp_out, "L_%p .part/v %s",
2046 net, draw_net_input(ivl_lpm_data(net,0)));
2047 fprintf(vvp_out, ", %s", draw_net_input(sel));
2048 fprintf(vvp_out, ", %u;\n", width);
2053 * Handle a PART SELECT PV device. Generate a .part/pv node that
2054 * includes the part input, and the geometry of the part.
2056 static void draw_lpm_part_pv(ivl_lpm_t net)
2058 unsigned width = ivl_lpm_width(net);
2059 unsigned base = ivl_lpm_base(net);
2060 unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0));
2062 fprintf(vvp_out, "L_%p .part/pv %s",
2063 net, draw_net_input(ivl_lpm_data(net, 0)));
2065 fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width);
2069 * Handle the drawing of a bi-directional part select. The two ports
2070 * are simultaneously input and output. A simple minded connect of the
2071 * input to the output causes a functor cycle which will lock into an
2072 * X value, so something special is needed.
2074 * NOTE: The inputs of the tran device at this point need to be from
2075 * all the drivers of the nexus *except* the tran itself. This
2076 * function will draw three labels that can be linked:
2078 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2079 * ivl_lpm_data, the tran acts like a forward part select in that
2080 * way.
2082 * The device creates these nodes:
2084 * - L_%p/i
2085 * This is the Q port of the tran resolved and padded to the maximum
2086 * width of the tran. The tran itself is not included in the
2087 * resolution of this port.
2089 * - L_%p/V
2090 * This is the Q and D parts resolved together, still without the tran
2091 * driving anything.
2093 * - L_%p/P
2094 * This is the /V node part-selected back to the dimensions of the Q
2095 * side.
2097 static void draw_lpm_part_bi(ivl_lpm_t net)
2099 unsigned width = ivl_lpm_width(net);
2100 unsigned base = ivl_lpm_base(net);
2101 unsigned signal_width = width_of_nexus(ivl_lpm_data(net,0));
2103 unsigned idx;
2104 ivl_nexus_t nex;
2105 ivl_nexus_ptr_t ptr = 0;
2107 char*p_str;
2108 char*v_str;
2110 /* It seems implausible that the two inputs of a tran will be
2111 connected together. So assert that this is so to simplify
2112 the code to look for the nexus_ptr_t objects. */
2113 assert(ivl_lpm_q(net,0) != ivl_lpm_data(net,0));
2115 nex = ivl_lpm_q(net,0);
2116 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
2117 ptr = ivl_nexus_ptr(nex, idx);
2118 if (ivl_nexus_ptr_lpm(ptr) == net)
2119 break;
2121 assert(ptr != 0);
2122 p_str = draw_net_input_x(nex, ptr, 0, 0);
2124 nex = ivl_lpm_data(net,0);
2125 for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
2126 ptr = ivl_nexus_ptr(nex, idx);
2127 if (ivl_nexus_ptr_lpm(ptr) == net)
2128 break;
2130 v_str = draw_net_input_x(nex, ptr, OMIT_PART_BI_DATA, 0);
2132 /* Pad the part-sized input out to a common width...
2133 The /i label is the Q side of the tran, resolved except for
2134 the tran itself and padded (with z) to the larger width. */
2135 fprintf(vvp_out, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2136 net, p_str, base, width, signal_width);
2138 /* Resolve together the two halves of the tran...
2139 The /V label is the ports of the tran (now the same width)
2140 resolved together. Neither input to this resolver includes
2141 the tran itself. */
2142 fprintf(vvp_out, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2143 net, net, v_str);
2145 /* The full-width side is created by the tran device, all we
2146 have left to to is take a part select of that for the
2147 smaller output, and this becomes the part select output of
2148 the BI device. */
2149 fprintf(vvp_out, "L_%p/P .part L_%p/V, %u, %u;\n", net,
2150 net, base, width);
2152 free(p_str);
2153 free(v_str);
2157 * Draw unary reduction devices.
2159 static void draw_lpm_re(ivl_lpm_t net, const char*type)
2161 fprintf(vvp_out, "L_%p .reduce/%s %s;\n",
2162 net, type, draw_net_input(ivl_lpm_data(net,0)));
2165 static void draw_lpm_repeat(ivl_lpm_t net)
2167 fprintf(vvp_out, "L_%p .repeat %u, %u, %s;\n", net,
2168 ivl_lpm_width(net), ivl_lpm_size(net),
2169 draw_net_input(ivl_lpm_data(net,0)));
2172 static void draw_lpm_sign_ext(ivl_lpm_t net)
2174 fprintf(vvp_out, "L_%p .extend/s %u, %s;\n",
2175 net, ivl_lpm_width(net),
2176 draw_net_input(ivl_lpm_data(net,0)));
2179 static void draw_lpm_in_scope(ivl_lpm_t net)
2181 switch (ivl_lpm_type(net)) {
2183 case IVL_LPM_ADD:
2184 case IVL_LPM_SUB:
2185 case IVL_LPM_MULT:
2186 case IVL_LPM_DIVIDE:
2187 case IVL_LPM_MOD:
2188 draw_lpm_add(net);
2189 return;
2191 case IVL_LPM_ARRAY:
2192 draw_lpm_array(net);
2193 return;
2195 case IVL_LPM_PART_BI:
2196 draw_lpm_part_bi(net);
2197 return;
2199 case IVL_LPM_PART_VP:
2200 draw_lpm_part(net);
2201 return;
2203 case IVL_LPM_PART_PV:
2204 draw_lpm_part_pv(net);
2205 return;
2207 case IVL_LPM_CONCAT:
2208 draw_lpm_concat(net);
2209 return;
2211 case IVL_LPM_FF:
2212 draw_lpm_ff(net);
2213 return;
2215 case IVL_LPM_CMP_EEQ:
2216 case IVL_LPM_CMP_EQ:
2217 case IVL_LPM_CMP_GE:
2218 case IVL_LPM_CMP_GT:
2219 case IVL_LPM_CMP_NE:
2220 case IVL_LPM_CMP_NEE:
2221 draw_lpm_cmp(net);
2222 return;
2224 case IVL_LPM_MUX:
2225 draw_lpm_mux(net);
2226 return;
2228 case IVL_LPM_RE_AND:
2229 draw_lpm_re(net, "and");
2230 return;
2231 case IVL_LPM_RE_OR:
2232 draw_lpm_re(net, "or");
2233 return;
2234 case IVL_LPM_RE_XOR:
2235 draw_lpm_re(net, "xor");
2236 return;
2237 case IVL_LPM_RE_NAND:
2238 draw_lpm_re(net, "nand");
2239 return;
2240 case IVL_LPM_RE_NOR:
2241 draw_lpm_re(net, "nor");
2242 return;
2243 case IVL_LPM_RE_XNOR:
2244 draw_lpm_re(net, "xnor");
2245 return;
2247 case IVL_LPM_REPEAT:
2248 draw_lpm_repeat(net);
2249 return;
2251 case IVL_LPM_SHIFTL:
2252 case IVL_LPM_SHIFTR:
2253 draw_lpm_shiftl(net);
2254 return;
2256 case IVL_LPM_SIGN_EXT:
2257 draw_lpm_sign_ext(net);
2258 return;
2260 case IVL_LPM_SFUNC:
2261 draw_lpm_sfunc(net);
2262 return;
2264 case IVL_LPM_UFUNC:
2265 draw_lpm_ufunc(net);
2266 return;
2268 default:
2269 fprintf(stderr, "XXXX LPM not supported: %s.%s\n",
2270 ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net));
2274 int draw_scope(ivl_scope_t net, ivl_scope_t parent)
2276 unsigned idx;
2277 const char *type;
2278 switch (ivl_scope_type(net)) {
2279 case IVL_SCT_MODULE: type = "module"; break;
2280 case IVL_SCT_FUNCTION: type = "function"; break;
2281 case IVL_SCT_TASK: type = "task"; break;
2282 case IVL_SCT_BEGIN: type = "begin"; break;
2283 case IVL_SCT_FORK: type = "fork"; break;
2284 case IVL_SCT_GENERATE: type = "generate"; break;
2285 default: type = "?"; assert(0);
2288 fprintf(vvp_out, "S_%p .scope %s, \"%s\" \"%s\"",
2289 net, type, vvp_mangle_name(ivl_scope_basename(net)),
2290 ivl_scope_tname(net));
2292 if (parent) {
2293 fprintf(vvp_out, ", S_%p;\n", parent);
2294 } else {
2296 fprintf(vvp_out, ";\n");
2299 fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net),
2300 ivl_scope_time_precision(net));
2302 for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) {
2303 ivl_parameter_t par = ivl_scope_param(net, idx);
2304 ivl_expr_t pex = ivl_parameter_expr(par);
2305 switch (ivl_expr_type(pex)) {
2306 case IVL_EX_STRING:
2307 fprintf(vvp_out, "P_%p .param/str \"%s\", \"%s\";\n",
2308 par, ivl_parameter_basename(par),
2309 ivl_expr_string(pex));
2310 break;
2311 case IVL_EX_NUMBER:
2312 fprintf(vvp_out, "P_%p .param/l \"%s\", %sC4<",
2313 par, ivl_parameter_basename(par),
2314 ivl_expr_signed(pex)? "+":"");
2315 { const char*bits = ivl_expr_bits(pex);
2316 unsigned nbits = ivl_expr_width(pex);
2317 unsigned bb;
2318 for (bb = 0 ; bb < nbits; bb += 1)
2319 fprintf(vvp_out, "%c", bits[nbits-bb-1]);
2321 fprintf(vvp_out, ">;\n");
2322 break;
2323 default:
2324 fprintf(vvp_out, "; parameter type %d unsupported\n",
2325 ivl_expr_type(pex));
2326 break;
2330 /* Scan the scope for logic devices. For each device, draw out
2331 a functor that connects pin 0 to the output, and the
2332 remaining pins to inputs. */
2334 for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) {
2335 ivl_net_logic_t lptr = ivl_scope_log(net, idx);
2336 draw_logic_in_scope(lptr);
2340 /* Scan the signals (reg and net) and draw the appropriate
2341 statements to make the signal function. */
2343 for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) {
2344 ivl_signal_t sig = ivl_scope_sig(net, idx);
2346 switch (ivl_signal_type(sig)) {
2347 case IVL_SIT_REG:
2348 draw_reg_in_scope(sig);
2349 break;
2350 default:
2351 draw_net_in_scope(sig);
2352 break;
2356 for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) {
2357 ivl_event_t event = ivl_scope_event(net, idx);
2358 draw_event_in_scope(event);
2361 for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) {
2362 ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
2363 draw_lpm_in_scope(lpm);
2366 if (ivl_scope_type(net) == IVL_SCT_TASK)
2367 draw_task_definition(net);
2369 if (ivl_scope_type(net) == IVL_SCT_FUNCTION)
2370 draw_func_definition(net);
2372 ivl_scope_children(net, (ivl_scope_f*) draw_scope, net);
2373 return 0;