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 switch (bits
[ivl_const_width(cptr
)-idx
-1]) {
426 assert((dp
- result
) < result_len
);
433 static char* draw_C8_to_string(ivl_net_const_t cptr
,
434 ivl_drive_t dr0
, ivl_drive_t dr1
)
436 size_t nresult
= 5 + 3*ivl_const_width(cptr
);
437 char*result
= malloc(nresult
);
438 const char*bits
= ivl_const_bits(cptr
);
441 char dr0c
= "01234567"[dr0
];
442 char dr1c
= "01234567"[dr1
];
448 for (idx
= 0 ; idx
< ivl_const_width(cptr
) ; idx
+= 1) {
449 switch (bits
[ivl_const_width(cptr
)-idx
-1]) {
476 assert(dp
- result
< nresult
);
484 * This function takes a nexus and looks for an input functor. It then
485 * draws to the output a string that represents that functor. What we
486 * are trying to do here is find the input to the net that is attached
490 static char* draw_net_input_drive(ivl_nexus_t nex
, ivl_nexus_ptr_t nptr
)
492 unsigned nptr_pin
= ivl_nexus_ptr_pin(nptr
);
493 ivl_net_const_t cptr
;
494 ivl_net_logic_t lptr
;
498 lptr
= ivl_nexus_ptr_log(nptr
);
499 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_BUFZ
) && (nptr_pin
== 0))
501 if (! can_elide_bufz(lptr
, nptr
))
504 return strdup(draw_net_input(ivl_logic_pin(lptr
, 1)));
507 /* If this is a pulldown device, then there is a single pin
508 that drives a constant value to the entire width of the
509 vector. The driver normally drives a pull0 value, so a C8<>
510 constant is appropriate, but if the drive is really strong,
511 then we can draw a C4<> constant instead. */
512 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_PULLDOWN
)) {
513 if (ivl_nexus_ptr_drive0(nptr
) == IVL_DR_STRONG
) {
514 size_t result_len
= ivl_logic_width(lptr
) + 5;
515 char*result
= malloc(result_len
);
519 str_repeat(dp
, "0", ivl_logic_width(lptr
));
520 dp
+= ivl_logic_width(lptr
);
523 assert((dp
-result
) <= result_len
);
527 size_t result_len
= 3*ivl_logic_width(lptr
) + 5;
528 char*result
= malloc(result_len
);
531 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
538 str_repeat(dp
, val
, ivl_logic_width(lptr
));
539 dp
+= 3*ivl_logic_width(lptr
);
542 assert((dp
-result
) <= result_len
);
547 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_PULLUP
)) {
548 if (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_STRONG
) {
549 size_t result_len
= 5 + ivl_logic_width(lptr
);
550 char*result
= malloc(result_len
);
554 str_repeat(dp
, "1", ivl_logic_width(lptr
));
555 dp
+= ivl_logic_width(lptr
);
558 assert((dp
-result
) <= result_len
);
562 size_t result_len
= 5 + 3*ivl_logic_width(lptr
);
563 char*result
= malloc(result_len
);
566 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
573 str_repeat(dp
, val
, ivl_logic_width(lptr
));
574 dp
+= 3*ivl_logic_width(lptr
);
577 assert((dp
-result
) <= result_len
);
582 if (lptr
&& (nptr_pin
== 0)) {
584 snprintf(tmp
, sizeof tmp
, "L_%p", lptr
);
588 sptr
= ivl_nexus_ptr_sig(nptr
);
589 if (sptr
&& (ivl_signal_type(sptr
) == IVL_SIT_REG
)) {
591 /* Input is a .var. This device may be a non-zero pin
592 because it may be an array of reg vectors. */
593 snprintf(tmp
, sizeof tmp
, "v%p_%u", sptr
, nptr_pin
);
597 cptr
= ivl_nexus_ptr_con(nptr
);
599 /* Constants should have exactly 1 pin, with a literal value. */
600 assert(nptr_pin
== 0);
603 switch (ivl_const_type(cptr
)) {
606 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_STRONG
)
607 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_STRONG
)) {
609 result
= draw_C4_to_string(cptr
);
612 result
= draw_C8_to_string(cptr
,
613 ivl_nexus_ptr_drive0(nptr
),
614 ivl_nexus_ptr_drive1(nptr
));
620 snprintf(tmp
, sizeof(tmp
),
621 "Cr<%lg>", ivl_const_real(cptr
));
622 result
= strdup(tmp
);
634 lpm
= ivl_nexus_ptr_lpm(nptr
);
635 if (lpm
) switch (ivl_lpm_type(lpm
)) {
641 case IVL_LPM_CMP_EEQ
:
646 case IVL_LPM_CMP_NEE
:
650 case IVL_LPM_RE_NAND
:
652 case IVL_LPM_RE_XNOR
:
656 case IVL_LPM_SIGN_EXT
:
663 case IVL_LPM_PART_VP
:
664 case IVL_LPM_PART_PV
: /* NOTE: This is only a partial driver. */
666 if (ivl_lpm_q(lpm
, 0) == nex
) {
668 snprintf(tmp
, sizeof tmp
, "L_%p", lpm
);
673 case IVL_LPM_PART_BI
:
674 if (ivl_lpm_q(lpm
, 0) == nex
) {
676 snprintf(tmp
, sizeof tmp
, "L_%p/P", lpm
);
678 } else if (ivl_lpm_data(lpm
,0) == nex
) {
680 snprintf(tmp
, sizeof tmp
, "L_%p/V", lpm
);
686 fprintf(stderr
, "internal error: no input to nexus %s\n",
687 ivl_nexus_name(nex
));
689 return strdup("C<z>");
692 static void draw_modpath(const char*label
, const char*driver
,
693 ivl_signal_t path_sig
)
696 typedef const char*ccharp
;
700 src_drivers
= calloc(ivl_signal_npath(path_sig
), sizeof(ccharp
));
701 con_drivers
= calloc(ivl_signal_npath(path_sig
), sizeof(ccharp
));
702 for (idx
= 0 ; idx
< ivl_signal_npath(path_sig
) ; idx
+= 1) {
703 ivl_delaypath_t path
= ivl_signal_path(path_sig
, idx
);
704 ivl_nexus_t src
= ivl_path_source(path
);
705 ivl_nexus_t con
= ivl_path_condit(path
);
707 src_drivers
[idx
] = draw_net_input(src
);
709 if (con
) con_drivers
[idx
] = draw_net_input(con
);
710 else con_drivers
[idx
] = 0;
713 fprintf(vvp_out
, "%s .modpath %s", label
, driver
);
715 for (idx
= 0 ; idx
< ivl_signal_npath(path_sig
); idx
+= 1) {
716 ivl_delaypath_t path
= ivl_signal_path(path_sig
, idx
);
717 int ppos
= ivl_path_source_posedge(path
);
718 int pneg
= ivl_path_source_negedge(path
);
719 const char*edge
= ppos
? " +" : pneg
? " -" : "";
720 fprintf(vvp_out
, ",\n %s%s", src_drivers
[idx
], edge
);
722 " (%"PRIu64
",%"PRIu64
",%"PRIu64
723 ", %"PRIu64
",%"PRIu64
",%"PRIu64
724 ", %"PRIu64
",%"PRIu64
",%"PRIu64
725 ", %"PRIu64
",%"PRIu64
",%"PRIu64
,
726 ivl_path_delay(path
, IVL_PE_01
),
727 ivl_path_delay(path
, IVL_PE_10
),
728 ivl_path_delay(path
, IVL_PE_0z
),
729 ivl_path_delay(path
, IVL_PE_z1
),
730 ivl_path_delay(path
, IVL_PE_1z
),
731 ivl_path_delay(path
, IVL_PE_z0
),
732 ivl_path_delay(path
, IVL_PE_0x
),
733 ivl_path_delay(path
, IVL_PE_x1
),
734 ivl_path_delay(path
, IVL_PE_1x
),
735 ivl_path_delay(path
, IVL_PE_x0
),
736 ivl_path_delay(path
, IVL_PE_xz
),
737 ivl_path_delay(path
, IVL_PE_zx
));
739 if (con_drivers
[idx
]) {
740 fprintf(vvp_out
, " ? %s", con_drivers
[idx
]);
743 fprintf(vvp_out
, ")");
746 fprintf(vvp_out
, ";\n");
753 * This function draws the input to a net into a string. What that
754 * means is that it returns a static string that can be used to
755 * represent a resolved driver to a nexus. If there are multiple
756 * drivers to the nexus, then it writes out the resolver declarations
757 * needed to perform strength resolution.
759 * The string that this returns is malloced, and that means that the
760 * caller must free the string or store it permanently. This function
761 * does *not* check for a previously calculated string. Use the
762 * draw_net_input for the general case.
764 /* Omit LPMPART_BI device pin-data(0) drivers. */
765 # define OMIT_PART_BI_DATA 0x0001
767 static char* draw_net_input_x(ivl_nexus_t nex
,
768 ivl_nexus_ptr_t omit_ptr
, int omit_flags
,
769 struct vvp_nexus_data
*nex_data
)
771 ivl_signal_type_t res
;
775 unsigned ndrivers
= 0;
776 static ivl_nexus_ptr_t
*drivers
= 0x0;
777 static unsigned adrivers
= 0;
779 const char*resolv_type
;
781 char*nex_private
= 0;
783 /* Accumulate nex_data flags. */
786 res
= signal_type_of_nexus(nex
);
792 resolv_type
= "tri0";
793 nex_flags
|= VVP_NEXUS_DATA_STR
;
796 resolv_type
= "tri1";
797 nex_flags
|= VVP_NEXUS_DATA_STR
;
800 resolv_type
= "triand";
803 resolv_type
= "trior";
806 fprintf(stderr
, "vvp.tgt: Unsupported signal type: %u\n", res
);
813 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
815 ivl_nexus_ptr_t nptr
= ivl_nexus_ptr(nex
, idx
);
817 /* If we are supposed to skip LPM_PART_BI data pins,
818 check that this driver is that. */
819 if ((omit_flags
&OMIT_PART_BI_DATA
)
820 && (lpm_tmp
= ivl_nexus_ptr_lpm(nptr
))
821 && (nex
== ivl_lpm_data(lpm_tmp
,0)))
824 if (nptr
== omit_ptr
)
827 /* Skip input only pins. */
828 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_HiZ
)
829 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_HiZ
))
832 /* Mark the strength-aware flag if the driver can
833 generate values other than the standard "6"
835 if (ivl_nexus_ptr_drive0(nptr
) != IVL_DR_STRONG
)
836 nex_flags
|= VVP_NEXUS_DATA_STR
;
837 if (ivl_nexus_ptr_drive1(nptr
) != IVL_DR_STRONG
)
838 nex_flags
|= VVP_NEXUS_DATA_STR
;
840 /* Save this driver. */
841 if (ndrivers
>= adrivers
) {
843 drivers
= realloc(drivers
, adrivers
*sizeof(ivl_nexus_ptr_t
));
846 drivers
[ndrivers
] = nptr
;
850 /* If the caller is collecting nexus information, then save
851 the nexus driver count in the nex_data. */
853 nex_data
->drivers_count
= ndrivers
;
854 nex_data
->flags
|= nex_flags
;
857 /* If the nexus has no drivers, then send a constant HiZ into
860 unsigned idx
, wid
= width_of_nexus(nex
);
861 char*tmp
= malloc(wid
+ 5);
867 for (idx
= 0 ; idx
< wid
; idx
+= 1)
871 for (idx
= 0 ; idx
< wid
; idx
+= 1)
875 for (idx
= 0 ; idx
< wid
; idx
+= 1)
887 /* If the nexus has exactly one driver, then simply draw
888 it. Note that this will *not* work if the nexus is not a
890 if (ndrivers
== 1 && res
== IVL_SIT_TRI
) {
891 ivl_signal_t path_sig
= find_modpath(nex
);
893 char*nex_str
= draw_net_input_drive(nex
, drivers
[0]);
894 char modpath_label
[64];
895 snprintf(modpath_label
, sizeof modpath_label
,
897 draw_modpath(modpath_label
, nex_str
, path_sig
);
898 nex_private
= strdup(modpath_label
);
901 nex_private
= draw_net_input_drive(nex
, drivers
[0]);
909 for (inst
= 0; inst
< ndrivers
; inst
+= 4) {
911 fprintf(vvp_out
, "RS_%p/%d/%d .resolv tri",
914 fprintf(vvp_out
, "RS_%p .resolv %s",
917 for (idx
= inst
; idx
< ndrivers
&& idx
< inst
+4; idx
+= 1) {
919 fprintf(vvp_out
, ", RS_%p/%d/%d",
920 nex
, level
- 1, idx
*4);
922 char*drive
= draw_net_input_drive(nex
, drivers
[idx
]);
923 fprintf(vvp_out
, ", %s", drive
);
927 for ( ; idx
< inst
+4 ; idx
+= 1) {
928 fprintf(vvp_out
, ", ");
929 draw_C4_repeated_constant('z',width_of_nexus(nex
));
932 fprintf(vvp_out
, ";\n");
935 ndrivers
= (ndrivers
+3) / 4;
941 sprintf(result
, "RS_%p", nex
);
942 nex_private
= strdup(result
);
947 * Get a cached description of the nexus input, or create one if this
948 * nexus has not been cached yet. This is a wrapper for the common
949 * case call to draw_net_input_x.
951 const char*draw_net_input(ivl_nexus_t nex
)
953 struct vvp_nexus_data
*nex_data
= (struct vvp_nexus_data
*)
954 ivl_nexus_get_private(nex
);
956 /* If this nexus already has a label, then its input is
957 already figured out. Just return the existing label. */
958 if (nex_data
&& nex_data
->net_input
)
959 return nex_data
->net_input
;
962 nex_data
= new_nexus_data();
963 ivl_nexus_set_private(nex
, nex_data
);
966 assert(nex_data
->net_input
== 0);
967 nex_data
->net_input
= draw_net_input_x(nex
, 0, 0, nex_data
);
969 return nex_data
->net_input
;
972 const char*draw_input_from_net(ivl_nexus_t nex
)
974 static char result
[32];
977 ivl_signal_t sig
= signal_of_nexus(nex
, &word
);
979 return draw_net_input(nex
);
981 snprintf(result
, sizeof result
, "v%p_%u", sig
, word
);
987 * This function draws a reg/int/variable in the scope. This is a very
988 * simple device to draw as there are no inputs to connect so no need
989 * to scan the nexus. We do have to account for the possibility that
990 * the device is arrayed, though, by making a node for each array element.
992 static void draw_reg_in_scope(ivl_signal_t sig
)
994 int msb
= ivl_signal_msb(sig
);
995 int lsb
= ivl_signal_lsb(sig
);
997 const char*datatype_flag
= ivl_signal_integer(sig
) ? "/i" :
998 ivl_signal_signed(sig
)? "/s" : "";
1000 switch (ivl_signal_data_type(sig
)) {
1002 datatype_flag
= "/real";
1008 /* If the reg objects are collected into an array, then first
1009 write out the .array record to declare the array indices. */
1010 if (ivl_signal_dimensions(sig
) > 0) {
1011 unsigned word_count
= ivl_signal_array_count(sig
);
1012 int last
= ivl_signal_array_base(sig
)+word_count
-1;
1013 int first
= ivl_signal_array_base(sig
);
1014 fprintf(vvp_out
, "v%p .array%s \"%s\", %d %d, %d %d;\n",
1016 vvp_mangle_name(ivl_signal_basename(sig
)),
1017 last
, first
, msb
, lsb
);
1021 fprintf(vvp_out
, "v%p_0 .var%s \"%s\", %d %d;\n",
1023 vvp_mangle_name(ivl_signal_basename(sig
)), msb
, lsb
);
1029 * This function draws a net. This is a bit more complicated as we
1030 * have to find an appropriate functor to connect to the input.
1032 static void draw_net_in_scope(ivl_signal_t sig
)
1034 int msb
= ivl_signal_msb(sig
);
1035 int lsb
= ivl_signal_lsb(sig
);
1037 const char*datatype_flag
= ivl_signal_signed(sig
)? "/s" : "";
1040 /* Skip the local signal. */
1041 if (ivl_signal_local(sig
))
1044 switch (ivl_signal_data_type(sig
)) {
1046 datatype_flag
= "/real";
1052 for (iword
= 0 ; iword
< ivl_signal_array_count(sig
); iword
+= 1) {
1054 unsigned word_count
= ivl_signal_array_count(sig
);
1055 unsigned dimensions
= ivl_signal_dimensions(sig
);
1056 struct vvp_nexus_data
*nex_data
;
1058 /* Connect the pin of the signal to something. */
1059 ivl_nexus_t nex
= ivl_signal_nex(sig
, iword
);
1060 const char*driver
= draw_net_input(nex
);
1062 nex_data
= (struct vvp_nexus_data
*)ivl_nexus_get_private(nex
);
1065 if (nex_data
->net
== 0) {
1066 int strength_aware_flag
= 0;
1067 const char*vec8
= "";
1068 if (nex_data
->flags
&VVP_NEXUS_DATA_STR
)
1069 strength_aware_flag
= 1;
1070 if (nex_data
->drivers_count
> 1)
1072 if (strength_aware_flag
)
1075 if (iword
== 0 && dimensions
> 0) {
1076 int last
= ivl_signal_array_base(sig
) + word_count
-1;
1077 int first
= ivl_signal_array_base(sig
);
1078 fprintf(vvp_out
, "v%p .array \"%s\", %d %d;\n",
1079 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1082 if (dimensions
> 0) {
1083 /* If this is a word of an array, then use an
1084 array reference in place of the net name. */
1085 fprintf(vvp_out
, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1087 sig
, iword
, vec8
, datatype_flag
, sig
,
1088 iword
, msb
, lsb
, driver
,
1089 nex_data
->drivers_count
,
1090 strength_aware_flag
?", strength-aware":"");
1092 /* If this is an isolated word, it uses its
1094 assert(word_count
== 1);
1095 fprintf(vvp_out
, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
1097 sig
, iword
, vec8
, datatype_flag
,
1098 vvp_mangle_name(ivl_signal_basename(sig
)),
1100 nex_data
->drivers_count
,
1101 strength_aware_flag
?", strength-aware":"");
1103 nex_data
->net
= sig
;
1104 nex_data
->net_word
= iword
;
1106 } else if (dimensions
> 0) {
1108 /* In this case, we have an alias to an existing
1109 signal array. this typically is an instance of
1110 port collapsing that the elaborator combined to
1111 discover that the entire array can be collapsed,
1112 so the word count for the signal and the alias
1114 assert(word_count
== ivl_signal_array_count(nex_data
->net
));
1117 fprintf(vvp_out
, "v%p .array \"%s\", v%p; Alias to %s\n",
1118 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1119 nex_data
->net
, ivl_signal_basename(nex_data
->net
));
1121 /* An alias for the individual words? */
1123 fprintf(vvp_out
, "v%p_%u .alias%s v%p, %d %d, v%p_%u;\n",
1124 sig
, iword
, datatype_flag
, sig
,
1125 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1128 /* Finally, we may have an alias that is a word
1129 connected to another word. Again, this is a
1130 case of port collapsing. */
1132 /* For the alias, create a different kind of node
1133 that refers to the alias source data instead of
1134 holding our own data. */
1135 fprintf(vvp_out
, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1136 sig
, iword
, datatype_flag
,
1137 vvp_mangle_name(ivl_signal_basename(sig
)),
1138 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1143 static void draw_delay(ivl_net_logic_t lptr
)
1145 ivl_expr_t d0
= ivl_logic_delay(lptr
, 0);
1146 ivl_expr_t d1
= ivl_logic_delay(lptr
, 1);
1147 ivl_expr_t d2
= ivl_logic_delay(lptr
, 2);
1149 if (d0
== 0 && d1
== 0 && d2
== 0)
1152 /* FIXME: Assume that the expression is a constant */
1153 assert(number_is_immediate(d0
, 64));
1154 assert(number_is_immediate(d1
, 64));
1155 assert(number_is_immediate(d2
, 64));
1157 if (d0
== d1
&& d1
== d2
)
1158 fprintf(vvp_out
, " (%lu)", get_number_immediate(d0
));
1160 fprintf(vvp_out
, " (%lu,%lu,%lu)",
1161 get_number_immediate(d0
),
1162 get_number_immediate(d1
),
1163 get_number_immediate(d2
));
1166 static void draw_udp_def(ivl_udp_t udp
)
1171 switch (ivl_udp_init(udp
))
1184 if (ivl_udp_sequ(udp
))
1186 "UDP_%s .udp/sequ \"%s\", %d, %d",
1187 vvp_mangle_id(ivl_udp_name(udp
)),
1188 vvp_mangle_name(ivl_udp_name(udp
)),
1193 "UDP_%s .udp/comb \"%s\", %d",
1194 vvp_mangle_id(ivl_udp_name(udp
)),
1195 vvp_mangle_name(ivl_udp_name(udp
)),
1198 for (i
=0; i
<ivl_udp_rows(udp
); i
++)
1199 fprintf(vvp_out
, "\n ,\"%s\"", ivl_udp_row(udp
, i
) );
1201 fprintf(vvp_out
, ";\n");
1204 static void draw_udp_in_scope(ivl_net_logic_t lptr
)
1208 ivl_udp_t udp
= ivl_logic_udp(lptr
);
1210 static ivl_udp_t
*udps
= 0x0;
1211 static int nudps
= 0;
1214 for (i
=0; i
<nudps
; i
++)
1220 udps
= realloc(udps
, (nudps
+1)*sizeof(ivl_udp_t
));
1222 udps
[nudps
++] = udp
;
1226 fprintf(vvp_out
, "L_%p .udp", lptr
);
1227 fprintf(vvp_out
, " UDP_%s",
1228 vvp_mangle_id(ivl_udp_name(udp
)));
1231 for (pdx
= 1 ; pdx
< ivl_logic_pins(lptr
) ; pdx
+= 1) {
1232 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
);
1234 /* Unlike other logic gates, primitives may have unconnected
1235 inputs. The proper behavior is to attach a HiZ to the
1238 assert(ivl_logic_width(lptr
) == 1);
1239 fprintf(vvp_out
, ", C4<z>");
1242 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1246 fprintf(vvp_out
, ";\n");
1249 static void draw_logic_in_scope(ivl_net_logic_t lptr
)
1252 const char*ltype
= "?";
1253 const char*lcasc
= 0;
1254 char identity_val
= '0';
1256 int need_delay_flag
= ivl_logic_delay(lptr
,0)? 1 : 0;
1258 unsigned vector_width
= width_of_nexus(ivl_logic_pin(lptr
, 0));
1260 ivl_drive_t str0
, str1
;
1263 int ninp
= ivl_logic_pins(lptr
) - 1;
1264 typedef const char*const_charp
;
1265 const_charp
*input_strings
= calloc(ninp
, sizeof(const_charp
));
1267 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1) {
1268 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
+1);
1270 /* Only UDPs can have unconnected inputs. */
1271 assert(ivl_logic_type(lptr
) == IVL_LO_UDP
);
1272 input_strings
[pdx
] = 0;
1274 input_strings
[pdx
] = draw_net_input(nex
);
1278 switch (ivl_logic_type(lptr
)) {
1281 free(input_strings
);
1282 draw_udp_in_scope(lptr
);
1286 /* Draw bufz objects, but only if the gate cannot
1287 be elided. If I can elide it, then the
1288 draw_nex_input will take care of it for me. */
1289 ivl_nexus_ptr_t nptr
= ivl_logic_pin_ptr(lptr
,0);
1293 if (can_elide_bufz(lptr
, nptr
))
1299 case IVL_LO_PULLDOWN
:
1301 /* Skip pullup and pulldown objects. Things that have
1302 pull objects as inputs will instead generate the
1303 appropriate C<?> symbol. */
1304 free(input_strings
);
1385 fprintf(stderr
, "vvp.tgt: error: Unhandled logic type: %u\n",
1386 ivl_logic_type(lptr
));
1391 { ivl_nexus_t nex
= ivl_logic_pin(lptr
, 0);
1392 ivl_nexus_ptr_t nptr
= 0;
1394 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
1395 nptr
= ivl_nexus_ptr(nex
,idx
);
1396 if (ivl_nexus_ptr_log(nptr
) != lptr
)
1398 if (ivl_nexus_ptr_pin(nptr
) != 0)
1402 str0
= ivl_nexus_ptr_drive0(nptr
);
1403 str1
= ivl_nexus_ptr_drive1(nptr
);
1409 /* Get all the input label that I will use for parameters to
1410 the functor that I create later. */
1411 ninp
= ivl_logic_pins(lptr
) - 1;
1412 input_strings
= calloc(ninp
, sizeof(char*));
1413 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1)
1414 input_strings
[pdx
] = draw_net_input(ivl_logic_pin(lptr
, pdx
+1));
1417 ninp
= ivl_logic_pins(lptr
) - 1;
1420 for (inst
= 0; inst
< ninp
; inst
+= 4) {
1422 fprintf(vvp_out
, "L_%p/%d/%d .functor %s %u",
1423 lptr
, level
, inst
, lcasc
, vector_width
);
1425 fprintf(vvp_out
, "L_%p%s .functor %s %u",
1426 lptr
, need_delay_flag
? "/d" : "",
1427 ltype
, vector_width
);
1429 if (str0
!= IVL_DR_STRONG
|| str1
!= IVL_DR_STRONG
)
1430 fprintf(vvp_out
, " [%u %u]", str0
, str1
);
1433 for (pdx
= inst
; pdx
< ninp
&& pdx
< inst
+4 ; pdx
+= 1) {
1435 fprintf(vvp_out
, ", L_%p/%d/%d",
1436 lptr
, level
- 1, pdx
*4);
1438 fprintf(vvp_out
, ", %s", input_strings
[pdx
]);
1441 for ( ; pdx
< inst
+4 ; pdx
+= 1) {
1443 fprintf(vvp_out
, ", C4<");
1444 for (wdx
= 0 ; wdx
< vector_width
; wdx
+= 1)
1445 fprintf(vvp_out
, "%c", identity_val
);
1446 fprintf(vvp_out
, ">");
1449 fprintf(vvp_out
, ";\n");
1452 ninp
= (ninp
+3) / 4;
1458 /* Free the array of char*. The strings themselves are
1459 persistent, held by the ivl_nexus_t objects. */
1460 free(input_strings
);
1462 /* If there are delays, then draw the delay functor to carry
1463 that delay. This is the final output. */
1464 if (need_delay_flag
) {
1465 ivl_expr_t rise_exp
= ivl_logic_delay(lptr
,0);
1466 ivl_expr_t fall_exp
= ivl_logic_delay(lptr
,1);
1467 ivl_expr_t decay_exp
= ivl_logic_delay(lptr
,2);
1469 if (number_is_immediate(rise_exp
,64)
1470 && number_is_immediate(fall_exp
,64)
1471 && number_is_immediate(decay_exp
,64)) {
1473 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1474 lptr
, get_number_immediate(rise_exp
),
1475 get_number_immediate(rise_exp
),
1476 get_number_immediate(rise_exp
), lptr
);
1479 assert(ivl_expr_type(rise_exp
) == IVL_EX_SIGNAL
);
1480 assert(ivl_expr_type(fall_exp
) == IVL_EX_SIGNAL
);
1481 assert(ivl_expr_type(decay_exp
) == IVL_EX_SIGNAL
);
1483 fprintf(vvp_out
, "L_%p .delay L_%p/d", lptr
, lptr
);
1485 sig
= ivl_expr_signal(rise_exp
);
1486 assert(ivl_signal_array_count(sig
) == 1);
1487 fprintf(vvp_out
, ", v%p_0", sig
);
1489 sig
= ivl_expr_signal(fall_exp
);
1490 assert(ivl_signal_array_count(sig
) == 1);
1491 fprintf(vvp_out
, ", v%p_0", sig
);
1493 sig
= ivl_expr_signal(decay_exp
);
1494 assert(ivl_signal_array_count(sig
) == 1);
1495 fprintf(vvp_out
, ", v%p_0;\n", sig
);
1500 static void draw_event_in_scope(ivl_event_t obj
)
1502 unsigned nany
= ivl_event_nany(obj
);
1503 unsigned nneg
= ivl_event_nneg(obj
);
1504 unsigned npos
= ivl_event_npos(obj
);
1508 /* Figure out how many probe functors are needed. */
1510 cnt
+= (nany
+3) / 4;
1513 cnt
+= (nneg
+3) / 4;
1516 cnt
+= (npos
+3) / 4;
1519 /* If none are needed, then this is a named event. The
1520 code needed is easy. */
1521 fprintf(vvp_out
, "E_%p .event \"%s\";\n", obj
,
1522 vvp_mangle_name(ivl_event_basename(obj
)));
1524 } else if (cnt
> 1) {
1525 /* There are a bunch of events that need to be event/or
1530 for (idx
= 0 ; idx
< nany
; idx
+= 4, ecnt
+= 1) {
1533 fprintf(vvp_out
, "E_%p/%u .event edge", obj
, ecnt
);
1538 for (sub
= idx
; sub
< top
; sub
+= 1) {
1539 ivl_nexus_t nex
= ivl_event_any(obj
, sub
);
1540 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1542 fprintf(vvp_out
, ";\n");
1545 for (idx
= 0 ; idx
< nneg
; idx
+= 4, ecnt
+= 1) {
1548 fprintf(vvp_out
, "E_%p/%u .event negedge", obj
, ecnt
);
1553 for (sub
= idx
; sub
< top
; sub
+= 1) {
1554 ivl_nexus_t nex
= ivl_event_neg(obj
, sub
);
1555 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1557 fprintf(vvp_out
, ";\n");
1560 for (idx
= 0 ; idx
< npos
; idx
+= 4, ecnt
+= 1) {
1563 fprintf(vvp_out
, "E_%p/%u .event posedge", obj
, ecnt
);
1568 for (sub
= idx
; sub
< top
; sub
+= 1) {
1569 ivl_nexus_t nex
= ivl_event_pos(obj
, sub
);
1570 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1572 fprintf(vvp_out
, ";\n");
1575 assert(ecnt
== cnt
);
1577 fprintf(vvp_out
, "E_%p .event/or", obj
);
1578 fprintf(vvp_out
, " E_%p/0", obj
);
1580 for (idx
= 1 ; idx
< cnt
; idx
+= 1)
1581 fprintf(vvp_out
, ", E_%p/%u", obj
, idx
);
1583 fprintf(vvp_out
, ";\n");
1586 unsigned num_input_strings
= nany
+ nneg
+ npos
;
1588 ivl_nexus_t input_nexa
[4];
1589 const char*edge
= 0;
1591 assert(num_input_strings
<= 4);
1594 assert((nneg
+ npos
) == 0);
1599 for (idx
= 0 ; idx
< nany
; idx
+= 1) {
1600 ivl_nexus_t nex
= ivl_event_any(obj
, idx
);
1601 input_nexa
[idx
] = nex
;
1604 } else if (nneg
> 0) {
1605 assert((nany
+ npos
) == 0);
1608 for (idx
= 0 ; idx
< nneg
; idx
+= 1) {
1609 ivl_nexus_t nex
= ivl_event_neg(obj
, idx
);
1610 input_nexa
[idx
] = nex
;
1614 assert((nany
+ nneg
) == 0);
1617 for (idx
= 0 ; idx
< npos
; idx
+= 1) {
1618 ivl_nexus_t nex
= ivl_event_pos(obj
, idx
);
1619 input_nexa
[idx
] = nex
;
1623 fprintf(vvp_out
, "E_%p .event %s", obj
, edge
);
1624 for (idx
= 0 ; idx
< num_input_strings
; idx
+= 1)
1625 fprintf(vvp_out
, ", %s", draw_input_from_net(input_nexa
[idx
]));
1627 fprintf(vvp_out
, ";\n");
1632 * This function draws any functors needed to calculate the input to
1633 * this nexus, and leaves in the data array strings that can be used
1634 * as functor arguments. The strings are from the draw_net_input
1635 * function, which in turn returns nexus names, so the strings are
1636 * safe to pass around.
1638 static void draw_lpm_data_inputs(ivl_lpm_t net
, unsigned base
,
1639 unsigned ndata
, const char**src_table
)
1642 for (idx
= 0 ; idx
< ndata
; idx
+= 1) {
1643 ivl_nexus_t nex
= ivl_lpm_data(net
, base
+idx
);
1644 src_table
[idx
] = draw_net_input(nex
);
1648 static void draw_lpm_add(ivl_lpm_t net
)
1650 const char*src_table
[2];
1652 const char*type
= "";
1653 ivl_variable_type_t dta
= data_type_of_nexus(ivl_lpm_data(net
,0));
1654 ivl_variable_type_t dtb
= data_type_of_nexus(ivl_lpm_data(net
,1));
1655 ivl_variable_type_t dto
= IVL_VT_LOGIC
;
1657 if (dta
== IVL_VT_REAL
&& dtb
== IVL_VT_REAL
)
1660 width
= ivl_lpm_width(net
);
1662 switch (ivl_lpm_type(net
)) {
1667 if (dto
== IVL_VT_REAL
)
1675 case IVL_LPM_DIVIDE
:
1676 if (dto
== IVL_VT_REAL
)
1678 else if (ivl_lpm_signed(net
))
1690 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1691 fprintf(vvp_out
, "L_%p .arith/%s %u, %s, %s;\n",
1692 net
, type
, width
, src_table
[0], src_table
[1]);
1696 * The read port to an array is generated as a single record that takes
1697 * the address as an input.
1699 static void draw_lpm_array(ivl_lpm_t net
)
1702 ivl_signal_t mem
= ivl_lpm_array(net
);
1704 fprintf(vvp_out
, "L_%p .array/port v%p, ", net
, mem
);
1706 nex
= ivl_lpm_select(net
);
1707 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1709 fprintf(vvp_out
, ";\n");
1712 static void draw_lpm_cmp(ivl_lpm_t net
)
1714 const char*src_table
[2];
1716 const char*type
= "";
1717 const char*signed_string
= ivl_lpm_signed(net
)? ".s" : "";
1719 width
= ivl_lpm_width(net
);
1721 switch (ivl_lpm_type(net
)) {
1722 case IVL_LPM_CMP_EEQ
:
1726 case IVL_LPM_CMP_EQ
:
1730 case IVL_LPM_CMP_GE
:
1733 case IVL_LPM_CMP_GT
:
1736 case IVL_LPM_CMP_NE
:
1740 case IVL_LPM_CMP_NEE
:
1748 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1749 fprintf(vvp_out
, "L_%p .cmp/%s%s %u, %s, %s;\n",
1750 net
, type
, signed_string
, width
,
1751 src_table
[0], src_table
[1]);
1755 * This function draws the arguments to a .const node using the
1756 * lpm inputs starting at "start" and for "cnt" inputs. This input
1757 * count must be <= 4. It is up to the caller to write the header part
1758 * of the statement, and to organize the data into multiple
1761 * Return the width of the final concatenation.
1763 static unsigned lpm_concat_inputs(ivl_lpm_t net
, unsigned start
,
1764 unsigned cnt
, const char*src_table
[])
1771 /* First, draw the [L M N O] part of the statement, the list
1772 of widths for the .concat statement. */
1773 fprintf(vvp_out
, "[");
1775 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1776 ivl_nexus_t nex
= ivl_lpm_data(net
, start
+idx
);
1777 unsigned nexus_width
= width_of_nexus(nex
);
1778 fprintf(vvp_out
, " %u", nexus_width
);
1782 for ( ; idx
< 4 ; idx
+= 1)
1783 fprintf(vvp_out
, " 0");
1785 fprintf(vvp_out
, "]");
1788 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1789 fprintf(vvp_out
, ", %s", src_table
[idx
]);
1792 fprintf(vvp_out
, ";\n");
1797 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1798 * many nested nodes as necessary to support the desired number of
1801 static void draw_lpm_concat(ivl_lpm_t net
)
1803 const char*src_table
[4];
1804 unsigned icnt
= ivl_lpm_selects(net
);
1807 /* This is the easiest case. There are 4 or fewer input
1808 vectors, so the entire IVL_LPM_CONCAT can be
1809 implemented with a single .concat node. */
1810 draw_lpm_data_inputs(net
, 0, icnt
, src_table
);
1811 fprintf(vvp_out
, "L_%p .concat ", net
);
1812 lpm_concat_inputs(net
, 0, icnt
, src_table
);
1815 /* If there are more than 4 inputs, things get more
1816 complicated. We need to generate a balanced tree of
1817 .concat nodes to blend the inputs down to a single
1818 root node, that becomes the output from the
1820 unsigned idx
, depth
;
1821 struct concat_tree
{
1826 tree
= malloc((icnt
+ 3)/4 * sizeof(struct concat_tree
));
1828 /* First, fill in all the leaves with the initial inputs
1829 to the tree. After this loop, there are (icnt+3)/4
1830 .concat nodes drawn, that together take all the
1832 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1835 if ((idx
+ trans
) > icnt
)
1838 draw_lpm_data_inputs(net
, idx
, trans
, src_table
);
1839 fprintf(vvp_out
, "LS_%p_0_%u .concat ", net
, idx
);
1840 wid
= lpm_concat_inputs(net
, idx
, trans
, src_table
);
1842 tree
[idx
/4].base
= idx
;
1843 tree
[idx
/4].wid
= wid
;
1846 /* icnt is the input count for the level. It is the
1847 number of .concats of the previous level that have to
1848 be concatenated at the current level. (This is not
1849 the same as the bit width.) */
1850 icnt
= (icnt
+ 3)/4;
1852 /* Tree now has icnt nodes that are depth=0 concat nodes
1853 which take in the leaf inputs. The while loop below
1854 starts and ends with a tree of icnt nodes. Each time
1855 through, there are 1/4 the nodes we started
1856 with. Thus, we eventually get down to <=4 nodes, and
1857 that is when we fall out of the loop. */
1861 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1865 if ((idx
+trans
) > icnt
)
1868 fprintf(vvp_out
, "LS_%p_%u_%u .concat [",
1871 for (tdx
= 0 ; tdx
< trans
; tdx
+= 1) {
1872 fprintf(vvp_out
, " %u", tree
[idx
+tdx
].wid
);
1873 wid
+= tree
[idx
+tdx
].wid
;
1876 for ( ; tdx
< 4 ; tdx
+= 1)
1877 fprintf(vvp_out
, " 0");
1879 fprintf(vvp_out
, "]");
1881 for (tdx
= 0; tdx
< trans
; tdx
+= 1) {
1882 fprintf(vvp_out
, ", LS_%p_%u_%u", net
,
1883 depth
-1, tree
[idx
+tdx
].base
);
1886 fprintf(vvp_out
, ";\n");
1887 tree
[idx
/4].base
= idx
;
1888 tree
[idx
/4].wid
= wid
;
1892 icnt
= (icnt
+ 3)/4;
1895 /* Finally, draw the root node that takes in the final
1896 row of tree nodes and generates a single output. */
1897 fprintf(vvp_out
, "L_%p .concat [", net
);
1898 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1899 fprintf(vvp_out
, " %u", tree
[idx
].wid
);
1900 for ( ; idx
< 4 ; idx
+= 1)
1901 fprintf(vvp_out
, " 0");
1902 fprintf(vvp_out
, "]");
1904 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1905 fprintf(vvp_out
, ", LS_%p_%u_%u",
1906 net
, depth
-1, tree
[idx
].base
);
1908 fprintf(vvp_out
, ";\n");
1914 * primitive FD (q, clk, ce, d);
1919 * // clk ce d r s q q+
1920 * r 1 0 0 0 : ? : 0;
1921 * r 1 1 0 0 : ? : 1;
1922 * f 1 ? 0 0 : ? : -;
1923 * ? 1 ? 0 0 : ? : -;
1924 * * 0 ? 0 0 : ? : -;
1925 * ? ? ? 1 ? : ? : 0;
1926 * ? ? ? 0 1 : ? : 1;
1930 static void draw_lpm_ff(ivl_lpm_t net
)
1932 ivl_expr_t aset_expr
= 0;
1933 const char*aset_bits
= 0;
1938 width
= ivl_lpm_width(net
);
1940 aset_expr
= ivl_lpm_aset_value(net
);
1942 assert(ivl_expr_width(aset_expr
) == width
);
1943 aset_bits
= ivl_expr_bits(aset_expr
);
1947 fprintf(vvp_out
, "L_%p .dff ", net
);
1949 nex
= ivl_lpm_data(net
,0);
1951 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1953 nex
= ivl_lpm_clk(net
);
1955 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1957 nex
= ivl_lpm_enable(net
);
1959 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1961 fprintf(vvp_out
, ", C4<1>");
1964 /* Stub asynchronous input for now. */
1965 fprintf(vvp_out
, ", C4<z>");
1967 fprintf(vvp_out
, ";\n");
1970 static void draw_lpm_shiftl(ivl_lpm_t net
)
1972 unsigned width
= ivl_lpm_width(net
);
1973 const char* signed_flag
= ivl_lpm_signed(net
)? "s" : "";
1975 if (ivl_lpm_type(net
) == IVL_LPM_SHIFTR
)
1976 fprintf(vvp_out
, "L_%p .shift/r%s %u", net
, signed_flag
, width
);
1978 fprintf(vvp_out
, "L_%p .shift/l %u", net
, width
);
1980 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 0)));
1982 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 1)));
1984 fprintf(vvp_out
, ";\n");
1987 static void draw_type_string_of_nex(ivl_nexus_t nex
)
1989 switch (data_type_of_nexus(nex
)) {
1991 fprintf(vvp_out
, "r");
1995 fprintf(vvp_out
, "v%d", width_of_nexus(nex
));
2003 static void draw_lpm_sfunc(ivl_lpm_t net
)
2006 fprintf(vvp_out
, "L_%p .sfunc \"%s\"", net
, ivl_lpm_string(net
));
2008 /* Print the function type descriptor string. */
2009 fprintf(vvp_out
, ", \"");
2011 draw_type_string_of_nex(ivl_lpm_q(net
,0));
2013 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1)
2014 draw_type_string_of_nex(ivl_lpm_data(net
,idx
));
2016 fprintf(vvp_out
, "\"");
2018 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2019 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
,idx
)));
2022 fprintf(vvp_out
, ";\n");
2025 static void draw_lpm_ufunc(ivl_lpm_t net
)
2028 ivl_scope_t def
= ivl_lpm_define(net
);
2030 fprintf(vvp_out
, "L_%p .ufunc TD_%s, %u", net
,
2031 ivl_scope_name(def
),
2032 ivl_lpm_width(net
));
2034 /* Print all the net signals that connect to the input of the
2036 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2037 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, idx
)));
2041 assert((ivl_lpm_size(net
)+1) == ivl_scope_ports(def
));
2043 /* Now print all the variables in the function scope that
2044 receive the input values given in the previous list. */
2045 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2046 ivl_signal_t psig
= ivl_scope_port(def
, idx
+1);
2049 fprintf(vvp_out
, " (");
2051 fprintf(vvp_out
, ", ");
2053 assert(ivl_signal_array_count(psig
) == 1);
2054 fprintf(vvp_out
, "v%p_0", psig
);
2057 fprintf(vvp_out
, ")");
2059 /* Finally, print the reference to the signal from which the
2060 result is collected. */
2061 { ivl_signal_t psig
= ivl_scope_port(def
, 0);
2062 assert(ivl_lpm_width(net
) == ivl_signal_width(psig
));
2063 assert(ivl_signal_array_count(psig
) == 1);
2065 fprintf(vvp_out
, " v%p_0", psig
);
2068 fprintf(vvp_out
, ";\n");
2072 * Handle a PART SELECT device. This has a single input and output,
2073 * plus an optional extra input that is a non-constant base.
2075 static void draw_lpm_part(ivl_lpm_t net
)
2077 unsigned width
, base
;
2080 width
= ivl_lpm_width(net
);
2081 base
= ivl_lpm_base(net
);
2082 sel
= ivl_lpm_data(net
,1);
2085 fprintf(vvp_out
, "L_%p .part %s",
2086 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2087 fprintf(vvp_out
, ", %u, %u;\n", base
, width
);
2089 fprintf(vvp_out
, "L_%p .part/v %s",
2090 net
, draw_net_input(ivl_lpm_data(net
,0)));
2091 fprintf(vvp_out
, ", %s", draw_net_input(sel
));
2092 fprintf(vvp_out
, ", %u;\n", width
);
2097 * Handle a PART SELECT PV device. Generate a .part/pv node that
2098 * includes the part input, and the geometry of the part.
2100 static void draw_lpm_part_pv(ivl_lpm_t net
)
2102 unsigned width
= ivl_lpm_width(net
);
2103 unsigned base
= ivl_lpm_base(net
);
2104 unsigned signal_width
= width_of_nexus(ivl_lpm_q(net
,0));
2106 fprintf(vvp_out
, "L_%p .part/pv %s",
2107 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2109 fprintf(vvp_out
, ", %u, %u, %u;\n", base
, width
, signal_width
);
2113 * Handle the drawing of a bi-directional part select. The two ports
2114 * are simultaneously input and output. A simple minded connect of the
2115 * input to the output causes a functor cycle which will lock into an
2116 * X value, so something special is needed.
2118 * NOTE: The inputs of the tran device at this point need to be from
2119 * all the drivers of the nexus *except* the tran itself. This
2120 * function will draw three labels that can be linked:
2122 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2123 * ivl_lpm_data, the tran acts like a forward part select in that
2126 * The device creates these nodes:
2129 * This is the Q port of the tran resolved and padded to the maximum
2130 * width of the tran. The tran itself is not included in the
2131 * resolution of this port.
2134 * This is the Q and D parts resolved together, still without the tran
2138 * This is the /V node part-selected back to the dimensions of the Q
2141 static void draw_lpm_part_bi(ivl_lpm_t net
)
2143 unsigned width
= ivl_lpm_width(net
);
2144 unsigned base
= ivl_lpm_base(net
);
2145 unsigned signal_width
= width_of_nexus(ivl_lpm_data(net
,0));
2149 ivl_nexus_ptr_t ptr
= 0;
2154 /* It seems implausible that the two inputs of a tran will be
2155 connected together. So assert that this is so to simplify
2156 the code to look for the nexus_ptr_t objects. */
2157 assert(ivl_lpm_q(net
,0) != ivl_lpm_data(net
,0));
2159 nex
= ivl_lpm_q(net
,0);
2160 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2161 ptr
= ivl_nexus_ptr(nex
, idx
);
2162 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2166 p_str
= draw_net_input_x(nex
, ptr
, 0, 0);
2168 nex
= ivl_lpm_data(net
,0);
2169 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2170 ptr
= ivl_nexus_ptr(nex
, idx
);
2171 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2174 v_str
= draw_net_input_x(nex
, ptr
, OMIT_PART_BI_DATA
, 0);
2176 /* Pad the part-sized input out to a common width...
2177 The /i label is the Q side of the tran, resolved except for
2178 the tran itself and padded (with z) to the larger width. */
2179 fprintf(vvp_out
, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2180 net
, p_str
, base
, width
, signal_width
);
2182 /* Resolve together the two halves of the tran...
2183 The /V label is the ports of the tran (now the same width)
2184 resolved together. Neither input to this resolver includes
2186 fprintf(vvp_out
, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2189 /* The full-width side is created by the tran device, all we
2190 have left to to is take a part select of that for the
2191 smaller output, and this becomes the part select output of
2193 fprintf(vvp_out
, "L_%p/P .part L_%p/V, %u, %u;\n", net
,
2201 * Draw unary reduction devices.
2203 static void draw_lpm_re(ivl_lpm_t net
, const char*type
)
2205 fprintf(vvp_out
, "L_%p .reduce/%s %s;\n",
2206 net
, type
, draw_net_input(ivl_lpm_data(net
,0)));
2209 static void draw_lpm_repeat(ivl_lpm_t net
)
2211 fprintf(vvp_out
, "L_%p .repeat %u, %u, %s;\n", net
,
2212 ivl_lpm_width(net
), ivl_lpm_size(net
),
2213 draw_net_input(ivl_lpm_data(net
,0)));
2216 static void draw_lpm_sign_ext(ivl_lpm_t net
)
2218 fprintf(vvp_out
, "L_%p .extend/s %u, %s;\n",
2219 net
, ivl_lpm_width(net
),
2220 draw_net_input(ivl_lpm_data(net
,0)));
2223 static void draw_lpm_in_scope(ivl_lpm_t net
)
2225 switch (ivl_lpm_type(net
)) {
2230 case IVL_LPM_DIVIDE
:
2236 draw_lpm_array(net
);
2239 case IVL_LPM_PART_BI
:
2240 draw_lpm_part_bi(net
);
2243 case IVL_LPM_PART_VP
:
2247 case IVL_LPM_PART_PV
:
2248 draw_lpm_part_pv(net
);
2251 case IVL_LPM_CONCAT
:
2252 draw_lpm_concat(net
);
2259 case IVL_LPM_CMP_EEQ
:
2260 case IVL_LPM_CMP_EQ
:
2261 case IVL_LPM_CMP_GE
:
2262 case IVL_LPM_CMP_GT
:
2263 case IVL_LPM_CMP_NE
:
2264 case IVL_LPM_CMP_NEE
:
2272 case IVL_LPM_RE_AND
:
2273 draw_lpm_re(net
, "and");
2276 draw_lpm_re(net
, "or");
2278 case IVL_LPM_RE_XOR
:
2279 draw_lpm_re(net
, "xor");
2281 case IVL_LPM_RE_NAND
:
2282 draw_lpm_re(net
, "nand");
2284 case IVL_LPM_RE_NOR
:
2285 draw_lpm_re(net
, "nor");
2287 case IVL_LPM_RE_XNOR
:
2288 draw_lpm_re(net
, "xnor");
2291 case IVL_LPM_REPEAT
:
2292 draw_lpm_repeat(net
);
2295 case IVL_LPM_SHIFTL
:
2296 case IVL_LPM_SHIFTR
:
2297 draw_lpm_shiftl(net
);
2300 case IVL_LPM_SIGN_EXT
:
2301 draw_lpm_sign_ext(net
);
2305 draw_lpm_sfunc(net
);
2309 draw_lpm_ufunc(net
);
2313 fprintf(stderr
, "XXXX LPM not supported: %s.%s\n",
2314 ivl_scope_name(ivl_lpm_scope(net
)), ivl_lpm_basename(net
));
2318 int draw_scope(ivl_scope_t net
, ivl_scope_t parent
)
2322 switch (ivl_scope_type(net
)) {
2323 case IVL_SCT_MODULE
: type
= "module"; break;
2324 case IVL_SCT_FUNCTION
: type
= "function"; break;
2325 case IVL_SCT_TASK
: type
= "task"; break;
2326 case IVL_SCT_BEGIN
: type
= "begin"; break;
2327 case IVL_SCT_FORK
: type
= "fork"; break;
2328 case IVL_SCT_GENERATE
: type
= "generate"; break;
2329 default: type
= "?"; assert(0);
2332 fprintf(vvp_out
, "S_%p .scope %s, \"%s\" \"%s\"",
2333 net
, type
, vvp_mangle_name(ivl_scope_basename(net
)),
2334 ivl_scope_tname(net
));
2337 fprintf(vvp_out
, ", S_%p;\n", parent
);
2340 fprintf(vvp_out
, ";\n");
2343 fprintf(vvp_out
, " .timescale %d;\n", ivl_scope_time_units(net
));
2345 for (idx
= 0 ; idx
< ivl_scope_params(net
) ; idx
+= 1) {
2346 ivl_parameter_t par
= ivl_scope_param(net
, idx
);
2347 ivl_expr_t pex
= ivl_parameter_expr(par
);
2348 switch (ivl_expr_type(pex
)) {
2350 fprintf(vvp_out
, "P_%p .param/str \"%s\", \"%s\";\n",
2351 par
, ivl_parameter_basename(par
),
2352 ivl_expr_string(pex
));
2355 fprintf(vvp_out
, "P_%p .param/l \"%s\", %sC4<",
2356 par
, ivl_parameter_basename(par
),
2357 ivl_expr_signed(pex
)? "+":"");
2358 { const char*bits
= ivl_expr_bits(pex
);
2359 unsigned nbits
= ivl_expr_width(pex
);
2361 for (bb
= 0 ; bb
< nbits
; bb
+= 1)
2362 fprintf(vvp_out
, "%c", bits
[nbits
-bb
-1]);
2364 fprintf(vvp_out
, ">;\n");
2367 fprintf(vvp_out
, "; parameter type %d unsupported\n",
2368 ivl_expr_type(pex
));
2373 /* Scan the scope for logic devices. For each device, draw out
2374 a functor that connects pin 0 to the output, and the
2375 remaining pins to inputs. */
2377 for (idx
= 0 ; idx
< ivl_scope_logs(net
) ; idx
+= 1) {
2378 ivl_net_logic_t lptr
= ivl_scope_log(net
, idx
);
2379 draw_logic_in_scope(lptr
);
2383 /* Scan the signals (reg and net) and draw the appropriate
2384 statements to make the signal function. */
2386 for (idx
= 0 ; idx
< ivl_scope_sigs(net
) ; idx
+= 1) {
2387 ivl_signal_t sig
= ivl_scope_sig(net
, idx
);
2389 switch (ivl_signal_type(sig
)) {
2391 draw_reg_in_scope(sig
);
2394 draw_net_in_scope(sig
);
2399 for (idx
= 0 ; idx
< ivl_scope_events(net
) ; idx
+= 1) {
2400 ivl_event_t event
= ivl_scope_event(net
, idx
);
2401 draw_event_in_scope(event
);
2404 for (idx
= 0 ; idx
< ivl_scope_lpms(net
) ; idx
+= 1) {
2405 ivl_lpm_t lpm
= ivl_scope_lpm(net
, idx
);
2406 draw_lpm_in_scope(lpm
);
2409 if (ivl_scope_type(net
) == IVL_SCT_TASK
)
2410 draw_task_definition(net
);
2412 if (ivl_scope_type(net
) == IVL_SCT_FUNCTION
)
2413 draw_func_definition(net
);
2415 ivl_scope_children(net
, (ivl_scope_f
*) draw_scope
, net
);