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)
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 #ident "$Id: vvp_scope.c,v 1.160 2007/04/12 04:40:37 steve Exp $"
23 # include "vvp_priv.h"
29 # include <inttypes.h>
32 struct vvp_nexus_data
{
33 /* draw_net_input uses this */
35 unsigned drivers_count
;
37 /* draw_net_in_scope uses these to identify the controlling 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
));
51 * Escape non-symbol characters in ids, and quotes in strings.
54 inline static char hex_digit(unsigned i
)
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
;
69 const char nosym
[] = "!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~";
71 char *se
= strpbrk(inp
, nosym
);
77 unsigned int nlen
= strlen(id
) + 4*(++nesc
) + 1;
79 out
= realloc(out
, nlen
);
84 strncpy(out
+iout
, inp
, n
);
98 out
[iout
++] = hex_digit(*se
>> 4);
99 out
[iout
++] = hex_digit(*se
);
103 se
= strpbrk(inp
, nosym
);
106 strcpy(out
+iout
, inp
);
110 const char *vvp_mangle_name(const char *id
)
112 static char *out
= 0x0;
113 static size_t out_len
;
117 const char *inp
= id
;
119 const char nosym
[] = "\"\\";
121 char *se
= strpbrk(inp
, nosym
);
127 unsigned int nlen
= strlen(id
) + 2*(++nesc
) + 1;
128 if (out_len
< nlen
) {
129 out
= realloc(out
, nlen
);
134 strncpy(out
+iout
, inp
, n
);
141 se
= strpbrk(inp
, nosym
);
144 strcpy(out
+iout
, inp
);
148 static void draw_C4_repeated_constant(char bit_char
, unsigned width
)
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
)
162 size_t len
= strlen(str
);
163 for (idx
= 0 ; idx
< rpt
; idx
+= 1) {
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
175 const char* vvp_signal_label(ivl_signal_t sig
)
178 sprintf(buf
, "%p", sig
);
182 ivl_signal_t
signal_of_nexus(ivl_nexus_t nex
, unsigned*word
)
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
);
190 if (ivl_signal_local(sig
))
192 *word
= ivl_nexus_ptr_pin(ptr
);
199 ivl_signal_type_t
signal_type_of_nexus(ivl_nexus_t nex
)
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
);
211 stype
= ivl_signal_type(sig
);
212 if (stype
== IVL_SIT_REG
)
214 if (stype
== IVL_SIT_TRI
)
216 if (stype
== IVL_SIT_NONE
)
224 unsigned width_of_nexus(ivl_nexus_t nex
)
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
);
232 return ivl_signal_width(sig
);
238 ivl_variable_type_t
data_type_of_nexus(ivl_nexus_t nex
)
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
);
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
);
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
);
265 if (ivl_nexus_ptr_pin(ptr
) != pin
)
274 const char*drive_string(ivl_drive_t drive
)
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.
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.
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
)
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
);
343 /* If the gate carries a delay, it must remain. */
344 if (ivl_logic_delay(net
, 0) != 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))
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
)
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
)
366 if (ivl_nexus_ptr_drive1(in_np
) != dr1
)
372 /* If the BUFZ input has multiple drivers on its input, then
373 we need to keep this device in order to hide the
375 if (drive_count
!= 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
)
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
);
394 if (ivl_signal_npath(sig
) == 0)
403 static char* draw_C4_to_string(ivl_net_const_t cptr
)
405 const char*bits
= ivl_const_bits(cptr
);
408 size_t result_len
= 5 + ivl_const_width(cptr
);
409 char*result
= malloc(result_len
);
414 for (idx
= 0 ; idx
< ivl_const_width(cptr
) ; idx
+= 1) {
415 char bitchar
= bits
[ivl_const_width(cptr
)-idx
-1];
417 assert((dp
- result
) < result_len
);
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
);
432 char dr0c
= "01234567"[dr0
];
433 char dr1c
= "01234567"[dr1
];
439 for (idx
= 0 ; idx
< ivl_const_width(cptr
) ; idx
+= 1) {
440 switch (bits
[ivl_const_width(cptr
)-idx
-1]) {
467 assert(dp
- result
< nresult
);
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
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
;
489 lptr
= ivl_nexus_ptr_log(nptr
);
490 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_BUFZ
) && (nptr_pin
== 0))
492 if (! can_elide_bufz(lptr
, nptr
))
495 return strdup(draw_net_input(ivl_logic_pin(lptr
, 1)));
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
);
510 str_repeat(dp
, "0", ivl_logic_width(lptr
));
511 dp
+= ivl_logic_width(lptr
);
514 assert((dp
-result
) <= result_len
);
518 size_t result_len
= 3*ivl_logic_width(lptr
) + 5;
519 char*result
= malloc(result_len
);
522 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
529 str_repeat(dp
, val
, ivl_logic_width(lptr
));
530 dp
+= 3*ivl_logic_width(lptr
);
533 assert((dp
-result
) <= result_len
);
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
);
545 str_repeat(dp
, "1", ivl_logic_width(lptr
));
546 dp
+= ivl_logic_width(lptr
);
549 assert((dp
-result
) <= result_len
);
553 size_t result_len
= 5 + 3*ivl_logic_width(lptr
);
554 char*result
= malloc(result_len
);
557 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
564 str_repeat(dp
, val
, ivl_logic_width(lptr
));
565 dp
+= 3*ivl_logic_width(lptr
);
568 assert((dp
-result
) <= result_len
);
573 if (lptr
&& (nptr_pin
== 0)) {
575 snprintf(tmp
, sizeof tmp
, "L_%p", lptr
);
579 sptr
= ivl_nexus_ptr_sig(nptr
);
580 if (sptr
&& (ivl_signal_type(sptr
) == IVL_SIT_REG
)) {
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
);
588 cptr
= ivl_nexus_ptr_con(nptr
);
590 /* Constants should have exactly 1 pin, with a literal value. */
591 assert(nptr_pin
== 0);
594 switch (ivl_const_type(cptr
)) {
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
);
603 result
= draw_C8_to_string(cptr
,
604 ivl_nexus_ptr_drive0(nptr
),
605 ivl_nexus_ptr_drive1(nptr
));
611 snprintf(tmp
, sizeof(tmp
),
612 "Cr<%lg>", ivl_const_real(cptr
));
613 result
= strdup(tmp
);
625 lpm
= ivl_nexus_ptr_lpm(nptr
);
626 if (lpm
) switch (ivl_lpm_type(lpm
)) {
632 case IVL_LPM_CMP_EEQ
:
637 case IVL_LPM_CMP_NEE
:
641 case IVL_LPM_RE_NAND
:
643 case IVL_LPM_RE_XNOR
:
647 case IVL_LPM_SIGN_EXT
:
654 case IVL_LPM_PART_VP
:
655 case IVL_LPM_PART_PV
: /* NOTE: This is only a partial driver. */
657 if (ivl_lpm_q(lpm
, 0) == nex
) {
659 snprintf(tmp
, sizeof tmp
, "L_%p", lpm
);
664 case IVL_LPM_PART_BI
:
665 if (ivl_lpm_q(lpm
, 0) == nex
) {
667 snprintf(tmp
, sizeof tmp
, "L_%p/P", lpm
);
669 } else if (ivl_lpm_data(lpm
,0) == nex
) {
671 snprintf(tmp
, sizeof tmp
, "L_%p/V", lpm
);
677 fprintf(stderr
, "internal error: no input to nexus %s\n",
678 ivl_nexus_name(nex
));
680 return strdup("C<z>");
683 static void draw_modpath(const char*label
, const char*driver
,
684 ivl_signal_t path_sig
)
687 typedef const char*ccharp
;
691 src_drivers
= calloc(ivl_signal_npath(path_sig
), sizeof(ccharp
));
692 con_drivers
= calloc(ivl_signal_npath(path_sig
), sizeof(ccharp
));
693 for (idx
= 0 ; idx
< ivl_signal_npath(path_sig
) ; idx
+= 1) {
694 ivl_delaypath_t path
= ivl_signal_path(path_sig
, idx
);
695 ivl_nexus_t src
= ivl_path_source(path
);
696 ivl_nexus_t con
= ivl_path_condit(path
);
698 src_drivers
[idx
] = draw_net_input(src
);
700 if (con
) con_drivers
[idx
] = draw_net_input(con
);
701 else con_drivers
[idx
] = 0;
704 fprintf(vvp_out
, "%s .modpath %s", label
, driver
);
706 for (idx
= 0 ; idx
< ivl_signal_npath(path_sig
); idx
+= 1) {
707 ivl_delaypath_t path
= ivl_signal_path(path_sig
, idx
);
708 int ppos
= ivl_path_source_posedge(path
);
709 int pneg
= ivl_path_source_negedge(path
);
710 const char*edge
= ppos
? " +" : pneg
? " -" : "";
711 fprintf(vvp_out
, ",\n %s%s", src_drivers
[idx
], edge
);
713 " (%"PRIu64
",%"PRIu64
",%"PRIu64
714 ", %"PRIu64
",%"PRIu64
",%"PRIu64
715 ", %"PRIu64
",%"PRIu64
",%"PRIu64
716 ", %"PRIu64
",%"PRIu64
",%"PRIu64
,
717 ivl_path_delay(path
, IVL_PE_01
),
718 ivl_path_delay(path
, IVL_PE_10
),
719 ivl_path_delay(path
, IVL_PE_0z
),
720 ivl_path_delay(path
, IVL_PE_z1
),
721 ivl_path_delay(path
, IVL_PE_1z
),
722 ivl_path_delay(path
, IVL_PE_z0
),
723 ivl_path_delay(path
, IVL_PE_0x
),
724 ivl_path_delay(path
, IVL_PE_x1
),
725 ivl_path_delay(path
, IVL_PE_1x
),
726 ivl_path_delay(path
, IVL_PE_x0
),
727 ivl_path_delay(path
, IVL_PE_xz
),
728 ivl_path_delay(path
, IVL_PE_zx
));
730 if (con_drivers
[idx
]) {
731 fprintf(vvp_out
, " ? %s", con_drivers
[idx
]);
734 fprintf(vvp_out
, ")");
737 fprintf(vvp_out
, ";\n");
743 static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr
)
745 if (ivl_nexus_ptr_drive0(nptr
) != IVL_DR_STRONG
)
747 if (ivl_nexus_ptr_drive1(nptr
) != IVL_DR_STRONG
)
750 ivl_net_logic_t log
= ivl_nexus_ptr_log(nptr
);
752 /* These logic gates are able to generate unusual
753 strength values and so their outputs are considered
755 if (ivl_logic_type(log
) == IVL_LO_BUFIF0
)
757 if (ivl_logic_type(log
) == IVL_LO_BUFIF1
)
759 if (ivl_logic_type(log
) == IVL_LO_PMOS
)
761 if (ivl_logic_type(log
) == IVL_LO_NMOS
)
769 * This function draws the input to a net into a string. What that
770 * means is that it returns a static string that can be used to
771 * represent a resolved driver to a nexus. If there are multiple
772 * drivers to the nexus, then it writes out the resolver declarations
773 * needed to perform strength resolution.
775 * The string that this returns is malloced, and that means that the
776 * caller must free the string or store it permanently. This function
777 * does *not* check for a previously calculated string. Use the
778 * draw_net_input for the general case.
780 /* Omit LPMPART_BI device pin-data(0) drivers. */
781 # define OMIT_PART_BI_DATA 0x0001
783 static char* draw_net_input_x(ivl_nexus_t nex
,
784 ivl_nexus_ptr_t omit_ptr
, int omit_flags
,
785 struct vvp_nexus_data
*nex_data
)
787 ivl_signal_type_t res
;
791 unsigned ndrivers
= 0;
792 static ivl_nexus_ptr_t
*drivers
= 0x0;
793 static unsigned adrivers
= 0;
795 const char*resolv_type
;
797 char*nex_private
= 0;
799 /* Accumulate nex_data flags. */
802 res
= signal_type_of_nexus(nex
);
808 resolv_type
= "tri0";
809 nex_flags
|= VVP_NEXUS_DATA_STR
;
812 resolv_type
= "tri1";
813 nex_flags
|= VVP_NEXUS_DATA_STR
;
816 resolv_type
= "triand";
819 resolv_type
= "trior";
822 fprintf(stderr
, "vvp.tgt: Unsupported signal type: %u\n", res
);
829 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
831 ivl_nexus_ptr_t nptr
= ivl_nexus_ptr(nex
, idx
);
833 /* If we are supposed to skip LPM_PART_BI data pins,
834 check that this driver is that. */
835 if ((omit_flags
&OMIT_PART_BI_DATA
)
836 && (lpm_tmp
= ivl_nexus_ptr_lpm(nptr
))
837 && (nex
== ivl_lpm_data(lpm_tmp
,0)))
840 if (nptr
== omit_ptr
)
843 /* Skip input only pins. */
844 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_HiZ
)
845 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_HiZ
))
848 /* Mark the strength-aware flag if the driver can
849 generate values other than the standard "6"
851 if (nexus_drive_is_strength_aware(nptr
))
852 nex_flags
|= VVP_NEXUS_DATA_STR
;
854 /* Save this driver. */
855 if (ndrivers
>= adrivers
) {
857 drivers
= realloc(drivers
, adrivers
*sizeof(ivl_nexus_ptr_t
));
860 drivers
[ndrivers
] = nptr
;
864 /* If the caller is collecting nexus information, then save
865 the nexus driver count in the nex_data. */
867 nex_data
->drivers_count
= ndrivers
;
868 nex_data
->flags
|= nex_flags
;
871 /* If the nexus has no drivers, then send a constant HiZ into
874 unsigned idx
, wid
= width_of_nexus(nex
);
875 char*tmp
= malloc(wid
+ 5);
881 for (idx
= 0 ; idx
< wid
; idx
+= 1)
885 for (idx
= 0 ; idx
< wid
; idx
+= 1)
889 for (idx
= 0 ; idx
< wid
; idx
+= 1)
901 /* If the nexus has exactly one driver, then simply draw
902 it. Note that this will *not* work if the nexus is not a
904 if (ndrivers
== 1 && res
== IVL_SIT_TRI
) {
905 ivl_signal_t path_sig
= find_modpath(nex
);
907 char*nex_str
= draw_net_input_drive(nex
, drivers
[0]);
908 char modpath_label
[64];
909 snprintf(modpath_label
, sizeof modpath_label
,
911 draw_modpath(modpath_label
, nex_str
, path_sig
);
912 nex_private
= strdup(modpath_label
);
915 nex_private
= draw_net_input_drive(nex
, drivers
[0]);
923 for (inst
= 0; inst
< ndrivers
; inst
+= 4) {
925 fprintf(vvp_out
, "RS_%p/%d/%d .resolv tri",
928 fprintf(vvp_out
, "RS_%p .resolv %s",
931 for (idx
= inst
; idx
< ndrivers
&& idx
< inst
+4; idx
+= 1) {
933 fprintf(vvp_out
, ", RS_%p/%d/%d",
934 nex
, level
- 1, idx
*4);
936 char*drive
= draw_net_input_drive(nex
, drivers
[idx
]);
937 fprintf(vvp_out
, ", %s", drive
);
941 for ( ; idx
< inst
+4 ; idx
+= 1) {
942 fprintf(vvp_out
, ", ");
943 draw_C4_repeated_constant('z',width_of_nexus(nex
));
946 fprintf(vvp_out
, ";\n");
949 ndrivers
= (ndrivers
+3) / 4;
955 sprintf(result
, "RS_%p", nex
);
956 nex_private
= strdup(result
);
961 * Get a cached description of the nexus input, or create one if this
962 * nexus has not been cached yet. This is a wrapper for the common
963 * case call to draw_net_input_x.
965 const char*draw_net_input(ivl_nexus_t nex
)
967 struct vvp_nexus_data
*nex_data
= (struct vvp_nexus_data
*)
968 ivl_nexus_get_private(nex
);
970 /* If this nexus already has a label, then its input is
971 already figured out. Just return the existing label. */
972 if (nex_data
&& nex_data
->net_input
)
973 return nex_data
->net_input
;
976 nex_data
= new_nexus_data();
977 ivl_nexus_set_private(nex
, nex_data
);
980 assert(nex_data
->net_input
== 0);
981 nex_data
->net_input
= draw_net_input_x(nex
, 0, 0, nex_data
);
983 return nex_data
->net_input
;
986 const char*draw_input_from_net(ivl_nexus_t nex
)
988 static char result
[32];
991 ivl_signal_t sig
= signal_of_nexus(nex
, &word
);
993 return draw_net_input(nex
);
995 snprintf(result
, sizeof result
, "v%p_%u", sig
, word
);
1001 * This function draws a reg/int/variable in the scope. This is a very
1002 * simple device to draw as there are no inputs to connect so no need
1003 * to scan the nexus. We do have to account for the possibility that
1004 * the device is arrayed, though, by making a node for each array element.
1006 static void draw_reg_in_scope(ivl_signal_t sig
)
1008 int msb
= ivl_signal_msb(sig
);
1009 int lsb
= ivl_signal_lsb(sig
);
1011 const char*datatype_flag
= ivl_signal_integer(sig
) ? "/i" :
1012 ivl_signal_signed(sig
)? "/s" : "";
1014 switch (ivl_signal_data_type(sig
)) {
1016 datatype_flag
= "/real";
1022 /* If the reg objects are collected into an array, then first
1023 write out the .array record to declare the array indices. */
1024 if (ivl_signal_dimensions(sig
) > 0) {
1025 unsigned word_count
= ivl_signal_array_count(sig
);
1026 int last
= ivl_signal_array_base(sig
)+word_count
-1;
1027 int first
= ivl_signal_array_base(sig
);
1028 fprintf(vvp_out
, "v%p .array%s \"%s\", %d %d, %d %d;\n",
1030 vvp_mangle_name(ivl_signal_basename(sig
)),
1031 last
, first
, msb
, lsb
);
1035 fprintf(vvp_out
, "v%p_0 .var%s \"%s\", %d %d;\n",
1037 vvp_mangle_name(ivl_signal_basename(sig
)), msb
, lsb
);
1043 * This function draws a net. This is a bit more complicated as we
1044 * have to find an appropriate functor to connect to the input.
1046 static void draw_net_in_scope(ivl_signal_t sig
)
1048 int msb
= ivl_signal_msb(sig
);
1049 int lsb
= ivl_signal_lsb(sig
);
1051 const char*datatype_flag
= ivl_signal_signed(sig
)? "/s" : "";
1054 /* Skip the local signal. */
1055 if (ivl_signal_local(sig
))
1058 switch (ivl_signal_data_type(sig
)) {
1060 datatype_flag
= "/real";
1066 for (iword
= 0 ; iword
< ivl_signal_array_count(sig
); iword
+= 1) {
1068 unsigned word_count
= ivl_signal_array_count(sig
);
1069 unsigned dimensions
= ivl_signal_dimensions(sig
);
1070 struct vvp_nexus_data
*nex_data
;
1072 /* Connect the pin of the signal to something. */
1073 ivl_nexus_t nex
= ivl_signal_nex(sig
, iword
);
1074 const char*driver
= draw_net_input(nex
);
1076 nex_data
= (struct vvp_nexus_data
*)ivl_nexus_get_private(nex
);
1079 if (nex_data
->net
== 0) {
1080 int strength_aware_flag
= 0;
1081 const char*vec8
= "";
1082 if (nex_data
->flags
&VVP_NEXUS_DATA_STR
)
1083 strength_aware_flag
= 1;
1084 if (nex_data
->drivers_count
> 1)
1086 if (strength_aware_flag
)
1089 if (iword
== 0 && dimensions
> 0) {
1090 int last
= ivl_signal_array_base(sig
) + word_count
-1;
1091 int first
= ivl_signal_array_base(sig
);
1092 fprintf(vvp_out
, "v%p .array \"%s\", %d %d;\n",
1093 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1096 if (dimensions
> 0) {
1097 /* If this is a word of an array, then use an
1098 array reference in place of the net name. */
1099 fprintf(vvp_out
, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1101 sig
, iword
, vec8
, datatype_flag
, sig
,
1102 iword
, msb
, lsb
, driver
,
1103 nex_data
->drivers_count
,
1104 strength_aware_flag
?", strength-aware":"");
1106 /* If this is an isolated word, it uses its
1108 assert(word_count
== 1);
1109 fprintf(vvp_out
, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
1111 sig
, iword
, vec8
, datatype_flag
,
1112 vvp_mangle_name(ivl_signal_basename(sig
)),
1114 nex_data
->drivers_count
,
1115 strength_aware_flag
?", strength-aware":"");
1117 nex_data
->net
= sig
;
1118 nex_data
->net_word
= iword
;
1120 } else if (dimensions
> 0) {
1122 /* In this case, we have an alias to an existing
1123 signal array. this typically is an instance of
1124 port collapsing that the elaborator combined to
1125 discover that the entire array can be collapsed,
1126 so the word count for the signal and the alias
1128 assert(word_count
== ivl_signal_array_count(nex_data
->net
));
1131 fprintf(vvp_out
, "v%p .array \"%s\", v%p; Alias to %s\n",
1132 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1133 nex_data
->net
, ivl_signal_basename(nex_data
->net
));
1135 /* An alias for the individual words? */
1137 fprintf(vvp_out
, "v%p_%u .alias%s v%p, %d %d, v%p_%u;\n",
1138 sig
, iword
, datatype_flag
, sig
,
1139 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1142 /* Finally, we may have an alias that is a word
1143 connected to another word. Again, this is a
1144 case of port collapsing. */
1146 /* For the alias, create a different kind of node
1147 that refers to the alias source data instead of
1148 holding our own data. */
1149 fprintf(vvp_out
, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1150 sig
, iword
, datatype_flag
,
1151 vvp_mangle_name(ivl_signal_basename(sig
)),
1152 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1157 static void draw_delay(ivl_net_logic_t lptr
)
1159 ivl_expr_t d0
= ivl_logic_delay(lptr
, 0);
1160 ivl_expr_t d1
= ivl_logic_delay(lptr
, 1);
1161 ivl_expr_t d2
= ivl_logic_delay(lptr
, 2);
1163 if (d0
== 0 && d1
== 0 && d2
== 0)
1166 /* FIXME: Assume that the expression is a constant */
1167 assert(number_is_immediate(d0
, 64));
1168 assert(number_is_immediate(d1
, 64));
1169 assert(number_is_immediate(d2
, 64));
1171 if (d0
== d1
&& d1
== d2
)
1172 fprintf(vvp_out
, " (%lu)", get_number_immediate(d0
));
1174 fprintf(vvp_out
, " (%lu,%lu,%lu)",
1175 get_number_immediate(d0
),
1176 get_number_immediate(d1
),
1177 get_number_immediate(d2
));
1180 static void draw_udp_def(ivl_udp_t udp
)
1185 switch (ivl_udp_init(udp
))
1198 if (ivl_udp_sequ(udp
))
1200 "UDP_%s .udp/sequ \"%s\", %d, %d",
1201 vvp_mangle_id(ivl_udp_name(udp
)),
1202 vvp_mangle_name(ivl_udp_name(udp
)),
1207 "UDP_%s .udp/comb \"%s\", %d",
1208 vvp_mangle_id(ivl_udp_name(udp
)),
1209 vvp_mangle_name(ivl_udp_name(udp
)),
1212 for (i
=0; i
<ivl_udp_rows(udp
); i
++)
1213 fprintf(vvp_out
, "\n ,\"%s\"", ivl_udp_row(udp
, i
) );
1215 fprintf(vvp_out
, ";\n");
1218 static void draw_udp_in_scope(ivl_net_logic_t lptr
)
1222 ivl_udp_t udp
= ivl_logic_udp(lptr
);
1224 static ivl_udp_t
*udps
= 0x0;
1225 static int nudps
= 0;
1228 for (i
=0; i
<nudps
; i
++)
1234 udps
= realloc(udps
, (nudps
+1)*sizeof(ivl_udp_t
));
1236 udps
[nudps
++] = udp
;
1240 fprintf(vvp_out
, "L_%p .udp", lptr
);
1241 fprintf(vvp_out
, " UDP_%s",
1242 vvp_mangle_id(ivl_udp_name(udp
)));
1245 for (pdx
= 1 ; pdx
< ivl_logic_pins(lptr
) ; pdx
+= 1) {
1246 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
);
1248 /* Unlike other logic gates, primitives may have unconnected
1249 inputs. The proper behavior is to attach a HiZ to the
1252 assert(ivl_logic_width(lptr
) == 1);
1253 fprintf(vvp_out
, ", C4<z>");
1256 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1260 fprintf(vvp_out
, ";\n");
1263 static void draw_logic_in_scope(ivl_net_logic_t lptr
)
1266 const char*ltype
= "?";
1267 const char*lcasc
= 0;
1268 char identity_val
= '0';
1270 int need_delay_flag
= ivl_logic_delay(lptr
,0)? 1 : 0;
1272 unsigned vector_width
= width_of_nexus(ivl_logic_pin(lptr
, 0));
1274 ivl_drive_t str0
, str1
;
1277 int ninp
= ivl_logic_pins(lptr
) - 1;
1278 typedef const char*const_charp
;
1279 const_charp
*input_strings
= calloc(ninp
, sizeof(const_charp
));
1281 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1) {
1282 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
+1);
1284 /* Only UDPs can have unconnected inputs. */
1285 assert(ivl_logic_type(lptr
) == IVL_LO_UDP
);
1286 input_strings
[pdx
] = 0;
1288 input_strings
[pdx
] = draw_net_input(nex
);
1292 switch (ivl_logic_type(lptr
)) {
1295 free(input_strings
);
1296 draw_udp_in_scope(lptr
);
1300 /* Draw bufz objects, but only if the gate cannot
1301 be elided. If I can elide it, then the
1302 draw_nex_input will take care of it for me. */
1303 ivl_nexus_ptr_t nptr
= ivl_logic_pin_ptr(lptr
,0);
1307 if (can_elide_bufz(lptr
, nptr
))
1313 case IVL_LO_PULLDOWN
:
1315 /* Skip pullup and pulldown objects. Things that have
1316 pull objects as inputs will instead generate the
1317 appropriate C<?> symbol. */
1318 free(input_strings
);
1399 fprintf(stderr
, "vvp.tgt: error: Unhandled logic type: %u\n",
1400 ivl_logic_type(lptr
));
1405 { ivl_nexus_t nex
= ivl_logic_pin(lptr
, 0);
1406 ivl_nexus_ptr_t nptr
= 0;
1408 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
1409 nptr
= ivl_nexus_ptr(nex
,idx
);
1410 if (ivl_nexus_ptr_log(nptr
) != lptr
)
1412 if (ivl_nexus_ptr_pin(nptr
) != 0)
1416 str0
= ivl_nexus_ptr_drive0(nptr
);
1417 str1
= ivl_nexus_ptr_drive1(nptr
);
1423 /* Get all the input label that I will use for parameters to
1424 the functor that I create later. */
1425 ninp
= ivl_logic_pins(lptr
) - 1;
1426 input_strings
= calloc(ninp
, sizeof(char*));
1427 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1)
1428 input_strings
[pdx
] = draw_net_input(ivl_logic_pin(lptr
, pdx
+1));
1431 ninp
= ivl_logic_pins(lptr
) - 1;
1434 for (inst
= 0; inst
< ninp
; inst
+= 4) {
1436 fprintf(vvp_out
, "L_%p/%d/%d .functor %s %u",
1437 lptr
, level
, inst
, lcasc
, vector_width
);
1439 fprintf(vvp_out
, "L_%p%s .functor %s %u",
1440 lptr
, need_delay_flag
? "/d" : "",
1441 ltype
, vector_width
);
1443 if (str0
!= IVL_DR_STRONG
|| str1
!= IVL_DR_STRONG
)
1444 fprintf(vvp_out
, " [%u %u]", str0
, str1
);
1447 for (pdx
= inst
; pdx
< ninp
&& pdx
< inst
+4 ; pdx
+= 1) {
1449 fprintf(vvp_out
, ", L_%p/%d/%d",
1450 lptr
, level
- 1, pdx
*4);
1452 fprintf(vvp_out
, ", %s", input_strings
[pdx
]);
1455 for ( ; pdx
< inst
+4 ; pdx
+= 1) {
1457 fprintf(vvp_out
, ", C4<");
1458 for (wdx
= 0 ; wdx
< vector_width
; wdx
+= 1)
1459 fprintf(vvp_out
, "%c", identity_val
);
1460 fprintf(vvp_out
, ">");
1463 fprintf(vvp_out
, ";\n");
1466 ninp
= (ninp
+3) / 4;
1472 /* Free the array of char*. The strings themselves are
1473 persistent, held by the ivl_nexus_t objects. */
1474 free(input_strings
);
1476 /* If there are delays, then draw the delay functor to carry
1477 that delay. This is the final output. */
1478 if (need_delay_flag
) {
1479 ivl_expr_t rise_exp
= ivl_logic_delay(lptr
,0);
1480 ivl_expr_t fall_exp
= ivl_logic_delay(lptr
,1);
1481 ivl_expr_t decay_exp
= ivl_logic_delay(lptr
,2);
1483 if (number_is_immediate(rise_exp
,64)
1484 && number_is_immediate(fall_exp
,64)
1485 && number_is_immediate(decay_exp
,64)) {
1487 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1488 lptr
, get_number_immediate(rise_exp
),
1489 get_number_immediate(rise_exp
),
1490 get_number_immediate(rise_exp
), lptr
);
1493 assert(ivl_expr_type(rise_exp
) == IVL_EX_SIGNAL
);
1494 assert(ivl_expr_type(fall_exp
) == IVL_EX_SIGNAL
);
1495 assert(ivl_expr_type(decay_exp
) == IVL_EX_SIGNAL
);
1497 fprintf(vvp_out
, "L_%p .delay L_%p/d", lptr
, lptr
);
1499 sig
= ivl_expr_signal(rise_exp
);
1500 assert(ivl_signal_array_count(sig
) == 1);
1501 fprintf(vvp_out
, ", v%p_0", sig
);
1503 sig
= ivl_expr_signal(fall_exp
);
1504 assert(ivl_signal_array_count(sig
) == 1);
1505 fprintf(vvp_out
, ", v%p_0", sig
);
1507 sig
= ivl_expr_signal(decay_exp
);
1508 assert(ivl_signal_array_count(sig
) == 1);
1509 fprintf(vvp_out
, ", v%p_0;\n", sig
);
1514 static void draw_event_in_scope(ivl_event_t obj
)
1516 unsigned nany
= ivl_event_nany(obj
);
1517 unsigned nneg
= ivl_event_nneg(obj
);
1518 unsigned npos
= ivl_event_npos(obj
);
1522 /* Figure out how many probe functors are needed. */
1524 cnt
+= (nany
+3) / 4;
1527 cnt
+= (nneg
+3) / 4;
1530 cnt
+= (npos
+3) / 4;
1533 /* If none are needed, then this is a named event. The
1534 code needed is easy. */
1535 fprintf(vvp_out
, "E_%p .event \"%s\";\n", obj
,
1536 vvp_mangle_name(ivl_event_basename(obj
)));
1538 } else if (cnt
> 1) {
1539 /* There are a bunch of events that need to be event/or
1544 for (idx
= 0 ; idx
< nany
; idx
+= 4, ecnt
+= 1) {
1547 fprintf(vvp_out
, "E_%p/%u .event edge", obj
, ecnt
);
1552 for (sub
= idx
; sub
< top
; sub
+= 1) {
1553 ivl_nexus_t nex
= ivl_event_any(obj
, sub
);
1554 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1556 fprintf(vvp_out
, ";\n");
1559 for (idx
= 0 ; idx
< nneg
; idx
+= 4, ecnt
+= 1) {
1562 fprintf(vvp_out
, "E_%p/%u .event negedge", obj
, ecnt
);
1567 for (sub
= idx
; sub
< top
; sub
+= 1) {
1568 ivl_nexus_t nex
= ivl_event_neg(obj
, sub
);
1569 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1571 fprintf(vvp_out
, ";\n");
1574 for (idx
= 0 ; idx
< npos
; idx
+= 4, ecnt
+= 1) {
1577 fprintf(vvp_out
, "E_%p/%u .event posedge", obj
, ecnt
);
1582 for (sub
= idx
; sub
< top
; sub
+= 1) {
1583 ivl_nexus_t nex
= ivl_event_pos(obj
, sub
);
1584 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1586 fprintf(vvp_out
, ";\n");
1589 assert(ecnt
== cnt
);
1591 fprintf(vvp_out
, "E_%p .event/or", obj
);
1592 fprintf(vvp_out
, " E_%p/0", obj
);
1594 for (idx
= 1 ; idx
< cnt
; idx
+= 1)
1595 fprintf(vvp_out
, ", E_%p/%u", obj
, idx
);
1597 fprintf(vvp_out
, ";\n");
1600 unsigned num_input_strings
= nany
+ nneg
+ npos
;
1602 ivl_nexus_t input_nexa
[4];
1603 const char*edge
= 0;
1605 assert(num_input_strings
<= 4);
1608 assert((nneg
+ npos
) == 0);
1613 for (idx
= 0 ; idx
< nany
; idx
+= 1) {
1614 ivl_nexus_t nex
= ivl_event_any(obj
, idx
);
1615 input_nexa
[idx
] = nex
;
1618 } else if (nneg
> 0) {
1619 assert((nany
+ npos
) == 0);
1622 for (idx
= 0 ; idx
< nneg
; idx
+= 1) {
1623 ivl_nexus_t nex
= ivl_event_neg(obj
, idx
);
1624 input_nexa
[idx
] = nex
;
1628 assert((nany
+ nneg
) == 0);
1631 for (idx
= 0 ; idx
< npos
; idx
+= 1) {
1632 ivl_nexus_t nex
= ivl_event_pos(obj
, idx
);
1633 input_nexa
[idx
] = nex
;
1637 fprintf(vvp_out
, "E_%p .event %s", obj
, edge
);
1638 for (idx
= 0 ; idx
< num_input_strings
; idx
+= 1)
1639 fprintf(vvp_out
, ", %s", draw_input_from_net(input_nexa
[idx
]));
1641 fprintf(vvp_out
, ";\n");
1646 * This function draws any functors needed to calculate the input to
1647 * this nexus, and leaves in the data array strings that can be used
1648 * as functor arguments. The strings are from the draw_net_input
1649 * function, which in turn returns nexus names, so the strings are
1650 * safe to pass around.
1652 static void draw_lpm_data_inputs(ivl_lpm_t net
, unsigned base
,
1653 unsigned ndata
, const char**src_table
)
1656 for (idx
= 0 ; idx
< ndata
; idx
+= 1) {
1657 ivl_nexus_t nex
= ivl_lpm_data(net
, base
+idx
);
1658 src_table
[idx
] = draw_net_input(nex
);
1662 static void draw_lpm_add(ivl_lpm_t net
)
1664 const char*src_table
[2];
1666 const char*type
= "";
1667 ivl_variable_type_t dta
= data_type_of_nexus(ivl_lpm_data(net
,0));
1668 ivl_variable_type_t dtb
= data_type_of_nexus(ivl_lpm_data(net
,1));
1669 ivl_variable_type_t dto
= IVL_VT_LOGIC
;
1671 if (dta
== IVL_VT_REAL
&& dtb
== IVL_VT_REAL
)
1674 width
= ivl_lpm_width(net
);
1676 switch (ivl_lpm_type(net
)) {
1681 if (dto
== IVL_VT_REAL
)
1689 case IVL_LPM_DIVIDE
:
1690 if (dto
== IVL_VT_REAL
)
1692 else if (ivl_lpm_signed(net
))
1704 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1705 fprintf(vvp_out
, "L_%p .arith/%s %u, %s, %s;\n",
1706 net
, type
, width
, src_table
[0], src_table
[1]);
1710 * The read port to an array is generated as a single record that takes
1711 * the address as an input.
1713 static void draw_lpm_array(ivl_lpm_t net
)
1716 ivl_signal_t mem
= ivl_lpm_array(net
);
1718 fprintf(vvp_out
, "L_%p .array/port v%p, ", net
, mem
);
1720 nex
= ivl_lpm_select(net
);
1721 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1723 fprintf(vvp_out
, ";\n");
1726 static void draw_lpm_cmp(ivl_lpm_t net
)
1728 const char*src_table
[2];
1730 const char*type
= "";
1731 const char*signed_string
= ivl_lpm_signed(net
)? ".s" : "";
1733 width
= ivl_lpm_width(net
);
1735 switch (ivl_lpm_type(net
)) {
1736 case IVL_LPM_CMP_EEQ
:
1740 case IVL_LPM_CMP_EQ
:
1744 case IVL_LPM_CMP_GE
:
1747 case IVL_LPM_CMP_GT
:
1750 case IVL_LPM_CMP_NE
:
1754 case IVL_LPM_CMP_NEE
:
1762 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1763 fprintf(vvp_out
, "L_%p .cmp/%s%s %u, %s, %s;\n",
1764 net
, type
, signed_string
, width
,
1765 src_table
[0], src_table
[1]);
1769 * This function draws the arguments to a .const node using the
1770 * lpm inputs starting at "start" and for "cnt" inputs. This input
1771 * count must be <= 4. It is up to the caller to write the header part
1772 * of the statement, and to organize the data into multiple
1775 * Return the width of the final concatenation.
1777 static unsigned lpm_concat_inputs(ivl_lpm_t net
, unsigned start
,
1778 unsigned cnt
, const char*src_table
[])
1785 /* First, draw the [L M N O] part of the statement, the list
1786 of widths for the .concat statement. */
1787 fprintf(vvp_out
, "[");
1789 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1790 ivl_nexus_t nex
= ivl_lpm_data(net
, start
+idx
);
1791 unsigned nexus_width
= width_of_nexus(nex
);
1792 fprintf(vvp_out
, " %u", nexus_width
);
1796 for ( ; idx
< 4 ; idx
+= 1)
1797 fprintf(vvp_out
, " 0");
1799 fprintf(vvp_out
, "]");
1802 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1803 fprintf(vvp_out
, ", %s", src_table
[idx
]);
1806 fprintf(vvp_out
, ";\n");
1811 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1812 * many nested nodes as necessary to support the desired number of
1815 static void draw_lpm_concat(ivl_lpm_t net
)
1817 const char*src_table
[4];
1818 unsigned icnt
= ivl_lpm_selects(net
);
1821 /* This is the easiest case. There are 4 or fewer input
1822 vectors, so the entire IVL_LPM_CONCAT can be
1823 implemented with a single .concat node. */
1824 draw_lpm_data_inputs(net
, 0, icnt
, src_table
);
1825 fprintf(vvp_out
, "L_%p .concat ", net
);
1826 lpm_concat_inputs(net
, 0, icnt
, src_table
);
1829 /* If there are more than 4 inputs, things get more
1830 complicated. We need to generate a balanced tree of
1831 .concat nodes to blend the inputs down to a single
1832 root node, that becomes the output from the
1834 unsigned idx
, depth
;
1835 struct concat_tree
{
1840 tree
= malloc((icnt
+ 3)/4 * sizeof(struct concat_tree
));
1842 /* First, fill in all the leaves with the initial inputs
1843 to the tree. After this loop, there are (icnt+3)/4
1844 .concat nodes drawn, that together take all the
1846 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1849 if ((idx
+ trans
) > icnt
)
1852 draw_lpm_data_inputs(net
, idx
, trans
, src_table
);
1853 fprintf(vvp_out
, "LS_%p_0_%u .concat ", net
, idx
);
1854 wid
= lpm_concat_inputs(net
, idx
, trans
, src_table
);
1856 tree
[idx
/4].base
= idx
;
1857 tree
[idx
/4].wid
= wid
;
1860 /* icnt is the input count for the level. It is the
1861 number of .concats of the previous level that have to
1862 be concatenated at the current level. (This is not
1863 the same as the bit width.) */
1864 icnt
= (icnt
+ 3)/4;
1866 /* Tree now has icnt nodes that are depth=0 concat nodes
1867 which take in the leaf inputs. The while loop below
1868 starts and ends with a tree of icnt nodes. Each time
1869 through, there are 1/4 the nodes we started
1870 with. Thus, we eventually get down to <=4 nodes, and
1871 that is when we fall out of the loop. */
1875 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1879 if ((idx
+trans
) > icnt
)
1882 fprintf(vvp_out
, "LS_%p_%u_%u .concat [",
1885 for (tdx
= 0 ; tdx
< trans
; tdx
+= 1) {
1886 fprintf(vvp_out
, " %u", tree
[idx
+tdx
].wid
);
1887 wid
+= tree
[idx
+tdx
].wid
;
1890 for ( ; tdx
< 4 ; tdx
+= 1)
1891 fprintf(vvp_out
, " 0");
1893 fprintf(vvp_out
, "]");
1895 for (tdx
= 0; tdx
< trans
; tdx
+= 1) {
1896 fprintf(vvp_out
, ", LS_%p_%u_%u", net
,
1897 depth
-1, tree
[idx
+tdx
].base
);
1900 fprintf(vvp_out
, ";\n");
1901 tree
[idx
/4].base
= idx
;
1902 tree
[idx
/4].wid
= wid
;
1906 icnt
= (icnt
+ 3)/4;
1909 /* Finally, draw the root node that takes in the final
1910 row of tree nodes and generates a single output. */
1911 fprintf(vvp_out
, "L_%p .concat [", net
);
1912 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1913 fprintf(vvp_out
, " %u", tree
[idx
].wid
);
1914 for ( ; idx
< 4 ; idx
+= 1)
1915 fprintf(vvp_out
, " 0");
1916 fprintf(vvp_out
, "]");
1918 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1919 fprintf(vvp_out
, ", LS_%p_%u_%u",
1920 net
, depth
-1, tree
[idx
].base
);
1922 fprintf(vvp_out
, ";\n");
1928 * primitive FD (q, clk, ce, d);
1933 * // clk ce d r s q q+
1934 * r 1 0 0 0 : ? : 0;
1935 * r 1 1 0 0 : ? : 1;
1936 * f 1 ? 0 0 : ? : -;
1937 * ? 1 ? 0 0 : ? : -;
1938 * * 0 ? 0 0 : ? : -;
1939 * ? ? ? 1 ? : ? : 0;
1940 * ? ? ? 0 1 : ? : 1;
1944 static void draw_lpm_ff(ivl_lpm_t net
)
1946 ivl_expr_t aset_expr
= 0;
1947 const char*aset_bits
= 0;
1952 width
= ivl_lpm_width(net
);
1954 aset_expr
= ivl_lpm_aset_value(net
);
1956 assert(ivl_expr_width(aset_expr
) == width
);
1957 aset_bits
= ivl_expr_bits(aset_expr
);
1961 fprintf(vvp_out
, "L_%p .dff ", net
);
1963 nex
= ivl_lpm_data(net
,0);
1965 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1967 nex
= ivl_lpm_clk(net
);
1969 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1971 nex
= ivl_lpm_enable(net
);
1973 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1975 fprintf(vvp_out
, ", C4<1>");
1978 /* Stub asynchronous input for now. */
1979 fprintf(vvp_out
, ", C4<z>");
1981 fprintf(vvp_out
, ";\n");
1984 static void draw_lpm_shiftl(ivl_lpm_t net
)
1986 unsigned width
= ivl_lpm_width(net
);
1987 const char* signed_flag
= ivl_lpm_signed(net
)? "s" : "";
1989 if (ivl_lpm_type(net
) == IVL_LPM_SHIFTR
)
1990 fprintf(vvp_out
, "L_%p .shift/r%s %u", net
, signed_flag
, width
);
1992 fprintf(vvp_out
, "L_%p .shift/l %u", net
, width
);
1994 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 0)));
1996 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 1)));
1998 fprintf(vvp_out
, ";\n");
2001 static void draw_type_string_of_nex(ivl_nexus_t nex
)
2003 switch (data_type_of_nexus(nex
)) {
2005 fprintf(vvp_out
, "r");
2009 fprintf(vvp_out
, "v%d", width_of_nexus(nex
));
2017 static void draw_lpm_sfunc(ivl_lpm_t net
)
2020 fprintf(vvp_out
, "L_%p .sfunc \"%s\"", net
, ivl_lpm_string(net
));
2022 /* Print the function type descriptor string. */
2023 fprintf(vvp_out
, ", \"");
2025 draw_type_string_of_nex(ivl_lpm_q(net
,0));
2027 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1)
2028 draw_type_string_of_nex(ivl_lpm_data(net
,idx
));
2030 fprintf(vvp_out
, "\"");
2032 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2033 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
,idx
)));
2036 fprintf(vvp_out
, ";\n");
2039 static void draw_lpm_ufunc(ivl_lpm_t net
)
2042 ivl_scope_t def
= ivl_lpm_define(net
);
2044 fprintf(vvp_out
, "L_%p .ufunc TD_%s, %u", net
,
2045 ivl_scope_name(def
),
2046 ivl_lpm_width(net
));
2048 /* Print all the net signals that connect to the input of the
2050 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2051 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, idx
)));
2055 assert((ivl_lpm_size(net
)+1) == ivl_scope_ports(def
));
2057 /* Now print all the variables in the function scope that
2058 receive the input values given in the previous list. */
2059 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2060 ivl_signal_t psig
= ivl_scope_port(def
, idx
+1);
2063 fprintf(vvp_out
, " (");
2065 fprintf(vvp_out
, ", ");
2067 assert(ivl_signal_array_count(psig
) == 1);
2068 fprintf(vvp_out
, "v%p_0", psig
);
2071 fprintf(vvp_out
, ")");
2073 /* Finally, print the reference to the signal from which the
2074 result is collected. */
2075 { ivl_signal_t psig
= ivl_scope_port(def
, 0);
2076 assert(ivl_lpm_width(net
) == ivl_signal_width(psig
));
2077 assert(ivl_signal_array_count(psig
) == 1);
2079 fprintf(vvp_out
, " v%p_0", psig
);
2082 fprintf(vvp_out
, ";\n");
2086 * Handle a PART SELECT device. This has a single input and output,
2087 * plus an optional extra input that is a non-constant base.
2089 static void draw_lpm_part(ivl_lpm_t net
)
2091 unsigned width
, base
;
2094 width
= ivl_lpm_width(net
);
2095 base
= ivl_lpm_base(net
);
2096 sel
= ivl_lpm_data(net
,1);
2099 fprintf(vvp_out
, "L_%p .part %s",
2100 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2101 fprintf(vvp_out
, ", %u, %u;\n", base
, width
);
2103 fprintf(vvp_out
, "L_%p .part/v %s",
2104 net
, draw_net_input(ivl_lpm_data(net
,0)));
2105 fprintf(vvp_out
, ", %s", draw_net_input(sel
));
2106 fprintf(vvp_out
, ", %u;\n", width
);
2111 * Handle a PART SELECT PV device. Generate a .part/pv node that
2112 * includes the part input, and the geometry of the part.
2114 static void draw_lpm_part_pv(ivl_lpm_t net
)
2116 unsigned width
= ivl_lpm_width(net
);
2117 unsigned base
= ivl_lpm_base(net
);
2118 unsigned signal_width
= width_of_nexus(ivl_lpm_q(net
,0));
2120 fprintf(vvp_out
, "L_%p .part/pv %s",
2121 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2123 fprintf(vvp_out
, ", %u, %u, %u;\n", base
, width
, signal_width
);
2127 * Handle the drawing of a bi-directional part select. The two ports
2128 * are simultaneously input and output. A simple minded connect of the
2129 * input to the output causes a functor cycle which will lock into an
2130 * X value, so something special is needed.
2132 * NOTE: The inputs of the tran device at this point need to be from
2133 * all the drivers of the nexus *except* the tran itself. This
2134 * function will draw three labels that can be linked:
2136 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2137 * ivl_lpm_data, the tran acts like a forward part select in that
2140 * The device creates these nodes:
2143 * This is the Q port of the tran resolved and padded to the maximum
2144 * width of the tran. The tran itself is not included in the
2145 * resolution of this port.
2148 * This is the Q and D parts resolved together, still without the tran
2152 * This is the /V node part-selected back to the dimensions of the Q
2155 static void draw_lpm_part_bi(ivl_lpm_t net
)
2157 unsigned width
= ivl_lpm_width(net
);
2158 unsigned base
= ivl_lpm_base(net
);
2159 unsigned signal_width
= width_of_nexus(ivl_lpm_data(net
,0));
2163 ivl_nexus_ptr_t ptr
= 0;
2168 /* It seems implausible that the two inputs of a tran will be
2169 connected together. So assert that this is so to simplify
2170 the code to look for the nexus_ptr_t objects. */
2171 assert(ivl_lpm_q(net
,0) != ivl_lpm_data(net
,0));
2173 nex
= ivl_lpm_q(net
,0);
2174 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2175 ptr
= ivl_nexus_ptr(nex
, idx
);
2176 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2180 p_str
= draw_net_input_x(nex
, ptr
, 0, 0);
2182 nex
= ivl_lpm_data(net
,0);
2183 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2184 ptr
= ivl_nexus_ptr(nex
, idx
);
2185 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2188 v_str
= draw_net_input_x(nex
, ptr
, OMIT_PART_BI_DATA
, 0);
2190 /* Pad the part-sized input out to a common width...
2191 The /i label is the Q side of the tran, resolved except for
2192 the tran itself and padded (with z) to the larger width. */
2193 fprintf(vvp_out
, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2194 net
, p_str
, base
, width
, signal_width
);
2196 /* Resolve together the two halves of the tran...
2197 The /V label is the ports of the tran (now the same width)
2198 resolved together. Neither input to this resolver includes
2200 fprintf(vvp_out
, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2203 /* The full-width side is created by the tran device, all we
2204 have left to to is take a part select of that for the
2205 smaller output, and this becomes the part select output of
2207 fprintf(vvp_out
, "L_%p/P .part L_%p/V, %u, %u;\n", net
,
2215 * Draw unary reduction devices.
2217 static void draw_lpm_re(ivl_lpm_t net
, const char*type
)
2219 fprintf(vvp_out
, "L_%p .reduce/%s %s;\n",
2220 net
, type
, draw_net_input(ivl_lpm_data(net
,0)));
2223 static void draw_lpm_repeat(ivl_lpm_t net
)
2225 fprintf(vvp_out
, "L_%p .repeat %u, %u, %s;\n", net
,
2226 ivl_lpm_width(net
), ivl_lpm_size(net
),
2227 draw_net_input(ivl_lpm_data(net
,0)));
2230 static void draw_lpm_sign_ext(ivl_lpm_t net
)
2232 fprintf(vvp_out
, "L_%p .extend/s %u, %s;\n",
2233 net
, ivl_lpm_width(net
),
2234 draw_net_input(ivl_lpm_data(net
,0)));
2237 static void draw_lpm_in_scope(ivl_lpm_t net
)
2239 switch (ivl_lpm_type(net
)) {
2244 case IVL_LPM_DIVIDE
:
2250 draw_lpm_array(net
);
2253 case IVL_LPM_PART_BI
:
2254 draw_lpm_part_bi(net
);
2257 case IVL_LPM_PART_VP
:
2261 case IVL_LPM_PART_PV
:
2262 draw_lpm_part_pv(net
);
2265 case IVL_LPM_CONCAT
:
2266 draw_lpm_concat(net
);
2273 case IVL_LPM_CMP_EEQ
:
2274 case IVL_LPM_CMP_EQ
:
2275 case IVL_LPM_CMP_GE
:
2276 case IVL_LPM_CMP_GT
:
2277 case IVL_LPM_CMP_NE
:
2278 case IVL_LPM_CMP_NEE
:
2286 case IVL_LPM_RE_AND
:
2287 draw_lpm_re(net
, "and");
2290 draw_lpm_re(net
, "or");
2292 case IVL_LPM_RE_XOR
:
2293 draw_lpm_re(net
, "xor");
2295 case IVL_LPM_RE_NAND
:
2296 draw_lpm_re(net
, "nand");
2298 case IVL_LPM_RE_NOR
:
2299 draw_lpm_re(net
, "nor");
2301 case IVL_LPM_RE_XNOR
:
2302 draw_lpm_re(net
, "xnor");
2305 case IVL_LPM_REPEAT
:
2306 draw_lpm_repeat(net
);
2309 case IVL_LPM_SHIFTL
:
2310 case IVL_LPM_SHIFTR
:
2311 draw_lpm_shiftl(net
);
2314 case IVL_LPM_SIGN_EXT
:
2315 draw_lpm_sign_ext(net
);
2319 draw_lpm_sfunc(net
);
2323 draw_lpm_ufunc(net
);
2327 fprintf(stderr
, "XXXX LPM not supported: %s.%s\n",
2328 ivl_scope_name(ivl_lpm_scope(net
)), ivl_lpm_basename(net
));
2332 int draw_scope(ivl_scope_t net
, ivl_scope_t parent
)
2336 switch (ivl_scope_type(net
)) {
2337 case IVL_SCT_MODULE
: type
= "module"; break;
2338 case IVL_SCT_FUNCTION
: type
= "function"; break;
2339 case IVL_SCT_TASK
: type
= "task"; break;
2340 case IVL_SCT_BEGIN
: type
= "begin"; break;
2341 case IVL_SCT_FORK
: type
= "fork"; break;
2342 case IVL_SCT_GENERATE
: type
= "generate"; break;
2343 default: type
= "?"; assert(0);
2346 fprintf(vvp_out
, "S_%p .scope %s, \"%s\" \"%s\"",
2347 net
, type
, vvp_mangle_name(ivl_scope_basename(net
)),
2348 ivl_scope_tname(net
));
2351 fprintf(vvp_out
, ", S_%p;\n", parent
);
2354 fprintf(vvp_out
, ";\n");
2357 fprintf(vvp_out
, " .timescale %d %d;\n", ivl_scope_time_units(net
),
2358 ivl_scope_time_precision(net
));
2360 for (idx
= 0 ; idx
< ivl_scope_params(net
) ; idx
+= 1) {
2361 ivl_parameter_t par
= ivl_scope_param(net
, idx
);
2362 ivl_expr_t pex
= ivl_parameter_expr(par
);
2363 switch (ivl_expr_type(pex
)) {
2365 fprintf(vvp_out
, "P_%p .param/str \"%s\", \"%s\";\n",
2366 par
, ivl_parameter_basename(par
),
2367 ivl_expr_string(pex
));
2370 fprintf(vvp_out
, "P_%p .param/l \"%s\", %sC4<",
2371 par
, ivl_parameter_basename(par
),
2372 ivl_expr_signed(pex
)? "+":"");
2373 { const char*bits
= ivl_expr_bits(pex
);
2374 unsigned nbits
= ivl_expr_width(pex
);
2376 for (bb
= 0 ; bb
< nbits
; bb
+= 1)
2377 fprintf(vvp_out
, "%c", bits
[nbits
-bb
-1]);
2379 fprintf(vvp_out
, ">;\n");
2382 fprintf(vvp_out
, "; parameter type %d unsupported\n",
2383 ivl_expr_type(pex
));
2388 /* Scan the scope for logic devices. For each device, draw out
2389 a functor that connects pin 0 to the output, and the
2390 remaining pins to inputs. */
2392 for (idx
= 0 ; idx
< ivl_scope_logs(net
) ; idx
+= 1) {
2393 ivl_net_logic_t lptr
= ivl_scope_log(net
, idx
);
2394 draw_logic_in_scope(lptr
);
2398 /* Scan the signals (reg and net) and draw the appropriate
2399 statements to make the signal function. */
2401 for (idx
= 0 ; idx
< ivl_scope_sigs(net
) ; idx
+= 1) {
2402 ivl_signal_t sig
= ivl_scope_sig(net
, idx
);
2404 switch (ivl_signal_type(sig
)) {
2406 draw_reg_in_scope(sig
);
2409 draw_net_in_scope(sig
);
2414 for (idx
= 0 ; idx
< ivl_scope_events(net
) ; idx
+= 1) {
2415 ivl_event_t event
= ivl_scope_event(net
, idx
);
2416 draw_event_in_scope(event
);
2419 for (idx
= 0 ; idx
< ivl_scope_lpms(net
) ; idx
+= 1) {
2420 ivl_lpm_t lpm
= ivl_scope_lpm(net
, idx
);
2421 draw_lpm_in_scope(lpm
);
2424 if (ivl_scope_type(net
) == IVL_SCT_TASK
)
2425 draw_task_definition(net
);
2427 if (ivl_scope_type(net
) == IVL_SCT_FUNCTION
)
2428 draw_func_definition(net
);
2430 ivl_scope_children(net
, (ivl_scope_f
*) draw_scope
, net
);