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 int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr
)
685 if (ivl_nexus_ptr_drive0(nptr
) != IVL_DR_STRONG
)
687 if (ivl_nexus_ptr_drive1(nptr
) != IVL_DR_STRONG
)
690 ivl_net_logic_t log
= ivl_nexus_ptr_log(nptr
);
692 /* These logic gates are able to generate unusual
693 strength values and so their outputs are considered
695 if (ivl_logic_type(log
) == IVL_LO_BUFIF0
)
697 if (ivl_logic_type(log
) == IVL_LO_BUFIF1
)
699 if (ivl_logic_type(log
) == IVL_LO_PMOS
)
701 if (ivl_logic_type(log
) == IVL_LO_NMOS
)
703 if (ivl_logic_type(log
) == IVL_LO_CMOS
)
711 * This function draws the input to a net into a string. What that
712 * means is that it returns a static string that can be used to
713 * represent a resolved driver to a nexus. If there are multiple
714 * drivers to the nexus, then it writes out the resolver declarations
715 * needed to perform strength resolution.
717 * The string that this returns is malloced, and that means that the
718 * caller must free the string or store it permanently. This function
719 * does *not* check for a previously calculated string. Use the
720 * draw_net_input for the general case.
722 /* Omit LPMPART_BI device pin-data(0) drivers. */
723 # define OMIT_PART_BI_DATA 0x0001
725 static char* draw_net_input_x(ivl_nexus_t nex
,
726 ivl_nexus_ptr_t omit_ptr
, int omit_flags
,
727 struct vvp_nexus_data
*nex_data
)
729 ivl_signal_type_t res
;
733 unsigned ndrivers
= 0;
734 static ivl_nexus_ptr_t
*drivers
= 0x0;
735 static unsigned adrivers
= 0;
737 const char*resolv_type
;
739 char*nex_private
= 0;
741 /* Accumulate nex_data flags. */
744 res
= signal_type_of_nexus(nex
);
750 resolv_type
= "tri0";
751 nex_flags
|= VVP_NEXUS_DATA_STR
;
754 resolv_type
= "tri1";
755 nex_flags
|= VVP_NEXUS_DATA_STR
;
758 resolv_type
= "triand";
761 resolv_type
= "trior";
764 fprintf(stderr
, "vvp.tgt: Unsupported signal type: %u\n", res
);
771 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
773 ivl_nexus_ptr_t nptr
= ivl_nexus_ptr(nex
, idx
);
775 /* If we are supposed to skip LPM_PART_BI data pins,
776 check that this driver is that. */
777 if ((omit_flags
&OMIT_PART_BI_DATA
)
778 && (lpm_tmp
= ivl_nexus_ptr_lpm(nptr
))
779 && (nex
== ivl_lpm_data(lpm_tmp
,0)))
782 if (nptr
== omit_ptr
)
785 /* Skip input only pins. */
786 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_HiZ
)
787 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_HiZ
))
790 /* Mark the strength-aware flag if the driver can
791 generate values other than the standard "6"
793 if (nexus_drive_is_strength_aware(nptr
))
794 nex_flags
|= VVP_NEXUS_DATA_STR
;
796 /* Save this driver. */
797 if (ndrivers
>= adrivers
) {
799 drivers
= realloc(drivers
, adrivers
*sizeof(ivl_nexus_ptr_t
));
802 drivers
[ndrivers
] = nptr
;
806 /* If the caller is collecting nexus information, then save
807 the nexus driver count in the nex_data. */
809 nex_data
->drivers_count
= ndrivers
;
810 nex_data
->flags
|= nex_flags
;
813 /* If the nexus has no drivers, then send a constant HiZ into
816 unsigned idx
, wid
= width_of_nexus(nex
);
817 char*tmp
= malloc(wid
+ 5);
823 for (idx
= 0 ; idx
< wid
; idx
+= 1)
827 for (idx
= 0 ; idx
< wid
; idx
+= 1)
831 for (idx
= 0 ; idx
< wid
; idx
+= 1)
843 /* If the nexus has exactly one driver, then simply draw
844 it. Note that this will *not* work if the nexus is not a
846 if (ndrivers
== 1 && res
== IVL_SIT_TRI
) {
847 ivl_signal_t path_sig
= find_modpath(nex
);
849 char*nex_str
= draw_net_input_drive(nex
, drivers
[0]);
850 char modpath_label
[64];
851 snprintf(modpath_label
, sizeof modpath_label
,
853 nex_private
= strdup(modpath_label
);
854 draw_modpath(path_sig
, nex_str
);
857 nex_private
= draw_net_input_drive(nex
, drivers
[0]);
865 for (inst
= 0; inst
< ndrivers
; inst
+= 4) {
867 fprintf(vvp_out
, "RS_%p/%d/%d .resolv tri",
870 fprintf(vvp_out
, "RS_%p .resolv %s",
873 for (idx
= inst
; idx
< ndrivers
&& idx
< inst
+4; idx
+= 1) {
875 fprintf(vvp_out
, ", RS_%p/%d/%d",
876 nex
, level
- 1, idx
*4);
878 char*drive
= draw_net_input_drive(nex
, drivers
[idx
]);
879 fprintf(vvp_out
, ", %s", drive
);
883 for ( ; idx
< inst
+4 ; idx
+= 1) {
884 fprintf(vvp_out
, ", ");
885 draw_C4_repeated_constant('z',width_of_nexus(nex
));
888 fprintf(vvp_out
, ";\n");
891 ndrivers
= (ndrivers
+3) / 4;
897 sprintf(result
, "RS_%p", nex
);
898 nex_private
= strdup(result
);
903 * Get a cached description of the nexus input, or create one if this
904 * nexus has not been cached yet. This is a wrapper for the common
905 * case call to draw_net_input_x.
907 const char*draw_net_input(ivl_nexus_t nex
)
909 struct vvp_nexus_data
*nex_data
= (struct vvp_nexus_data
*)
910 ivl_nexus_get_private(nex
);
912 /* If this nexus already has a label, then its input is
913 already figured out. Just return the existing label. */
914 if (nex_data
&& nex_data
->net_input
)
915 return nex_data
->net_input
;
918 nex_data
= new_nexus_data();
919 ivl_nexus_set_private(nex
, nex_data
);
922 assert(nex_data
->net_input
== 0);
923 nex_data
->net_input
= draw_net_input_x(nex
, 0, 0, nex_data
);
925 return nex_data
->net_input
;
928 const char*draw_input_from_net(ivl_nexus_t nex
)
930 static char result
[32];
933 ivl_signal_t sig
= signal_of_nexus(nex
, &word
);
935 return draw_net_input(nex
);
937 snprintf(result
, sizeof result
, "v%p_%u", sig
, word
);
943 * This function draws a reg/int/variable in the scope. This is a very
944 * simple device to draw as there are no inputs to connect so no need
945 * to scan the nexus. We do have to account for the possibility that
946 * the device is arrayed, though, by making a node for each array element.
948 static void draw_reg_in_scope(ivl_signal_t sig
)
950 int msb
= ivl_signal_msb(sig
);
951 int lsb
= ivl_signal_lsb(sig
);
953 const char*datatype_flag
= ivl_signal_integer(sig
) ? "/i" :
954 ivl_signal_signed(sig
)? "/s" : "";
956 switch (ivl_signal_data_type(sig
)) {
958 datatype_flag
= "/real";
964 /* If the reg objects are collected into an array, then first
965 write out the .array record to declare the array indices. */
966 if (ivl_signal_dimensions(sig
) > 0) {
967 unsigned word_count
= ivl_signal_array_count(sig
);
968 int last
= ivl_signal_array_base(sig
)+word_count
-1;
969 int first
= ivl_signal_array_base(sig
);
970 fprintf(vvp_out
, "v%p .array%s \"%s\", %d %d, %d %d;\n",
972 vvp_mangle_name(ivl_signal_basename(sig
)),
973 last
, first
, msb
, lsb
);
977 fprintf(vvp_out
, "v%p_0 .var%s \"%s\", %d %d;\n",
979 vvp_mangle_name(ivl_signal_basename(sig
)), msb
, lsb
);
985 * This function draws a net. This is a bit more complicated as we
986 * have to find an appropriate functor to connect to the input.
988 static void draw_net_in_scope(ivl_signal_t sig
)
990 int msb
= ivl_signal_msb(sig
);
991 int lsb
= ivl_signal_lsb(sig
);
993 const char*datatype_flag
= ivl_signal_signed(sig
)? "/s" : "";
996 /* Skip the local signal. */
997 if (ivl_signal_local(sig
))
1000 switch (ivl_signal_data_type(sig
)) {
1002 datatype_flag
= "/real";
1008 for (iword
= 0 ; iword
< ivl_signal_array_count(sig
); iword
+= 1) {
1010 unsigned word_count
= ivl_signal_array_count(sig
);
1011 unsigned dimensions
= ivl_signal_dimensions(sig
);
1012 struct vvp_nexus_data
*nex_data
;
1014 /* Connect the pin of the signal to something. */
1015 ivl_nexus_t nex
= ivl_signal_nex(sig
, iword
);
1016 const char*driver
= draw_net_input(nex
);
1018 nex_data
= (struct vvp_nexus_data
*)ivl_nexus_get_private(nex
);
1021 if (nex_data
->net
== 0) {
1022 int strength_aware_flag
= 0;
1023 const char*vec8
= "";
1024 if (nex_data
->flags
&VVP_NEXUS_DATA_STR
)
1025 strength_aware_flag
= 1;
1026 if (nex_data
->drivers_count
> 1)
1028 if (strength_aware_flag
)
1031 if (iword
== 0 && dimensions
> 0) {
1032 int last
= ivl_signal_array_base(sig
) + word_count
-1;
1033 int first
= ivl_signal_array_base(sig
);
1034 fprintf(vvp_out
, "v%p .array \"%s\", %d %d;\n",
1035 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1038 if (dimensions
> 0) {
1039 /* If this is a word of an array, then use an
1040 array reference in place of the net name. */
1041 fprintf(vvp_out
, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1043 sig
, iword
, vec8
, datatype_flag
, sig
,
1044 iword
, msb
, lsb
, driver
,
1045 nex_data
->drivers_count
,
1046 strength_aware_flag
?", strength-aware":"");
1048 /* If this is an isolated word, it uses its
1050 assert(word_count
== 1);
1051 fprintf(vvp_out
, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
1053 sig
, iword
, vec8
, datatype_flag
,
1054 vvp_mangle_name(ivl_signal_basename(sig
)),
1056 nex_data
->drivers_count
,
1057 strength_aware_flag
?", strength-aware":"");
1059 nex_data
->net
= sig
;
1060 nex_data
->net_word
= iword
;
1062 } else if (dimensions
> 0) {
1064 /* In this case, we have an alias to an existing
1065 signal array. this typically is an instance of
1066 port collapsing that the elaborator combined to
1067 discover that the entire array can be collapsed,
1068 so the word count for the signal and the alias
1070 assert(word_count
== ivl_signal_array_count(nex_data
->net
));
1073 fprintf(vvp_out
, "v%p .array \"%s\", v%p; Alias to %s\n",
1074 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1075 nex_data
->net
, ivl_signal_basename(nex_data
->net
));
1077 /* An alias for the individual words? */
1079 fprintf(vvp_out
, "v%p_%u .alias%s v%p, %d %d, v%p_%u;\n",
1080 sig
, iword
, datatype_flag
, sig
,
1081 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1084 /* Finally, we may have an alias that is a word
1085 connected to another word. Again, this is a
1086 case of port collapsing. */
1088 /* For the alias, create a different kind of node
1089 that refers to the alias source data instead of
1090 holding our own data. */
1091 fprintf(vvp_out
, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1092 sig
, iword
, datatype_flag
,
1093 vvp_mangle_name(ivl_signal_basename(sig
)),
1094 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1099 static void draw_delay(ivl_net_logic_t lptr
)
1101 ivl_expr_t d0
= ivl_logic_delay(lptr
, 0);
1102 ivl_expr_t d1
= ivl_logic_delay(lptr
, 1);
1103 ivl_expr_t d2
= ivl_logic_delay(lptr
, 2);
1105 if (d0
== 0 && d1
== 0 && d2
== 0)
1108 /* FIXME: Assume that the expression is a constant */
1109 assert(number_is_immediate(d0
, 64));
1110 assert(number_is_immediate(d1
, 64));
1111 assert(number_is_immediate(d2
, 64));
1113 if (d0
== d1
&& d1
== d2
)
1114 fprintf(vvp_out
, " (%lu)", get_number_immediate(d0
));
1116 fprintf(vvp_out
, " (%lu,%lu,%lu)",
1117 get_number_immediate(d0
),
1118 get_number_immediate(d1
),
1119 get_number_immediate(d2
));
1122 static void draw_udp_def(ivl_udp_t udp
)
1127 switch (ivl_udp_init(udp
))
1140 if (ivl_udp_sequ(udp
))
1142 "UDP_%s .udp/sequ \"%s\", %d, %d",
1143 vvp_mangle_id(ivl_udp_name(udp
)),
1144 vvp_mangle_name(ivl_udp_name(udp
)),
1149 "UDP_%s .udp/comb \"%s\", %d",
1150 vvp_mangle_id(ivl_udp_name(udp
)),
1151 vvp_mangle_name(ivl_udp_name(udp
)),
1154 for (i
=0; i
<ivl_udp_rows(udp
); i
++)
1155 fprintf(vvp_out
, "\n ,\"%s\"", ivl_udp_row(udp
, i
) );
1157 fprintf(vvp_out
, ";\n");
1160 static void draw_udp_in_scope(ivl_net_logic_t lptr
)
1164 ivl_udp_t udp
= ivl_logic_udp(lptr
);
1166 static ivl_udp_t
*udps
= 0x0;
1167 static int nudps
= 0;
1170 for (i
=0; i
<nudps
; i
++)
1176 udps
= realloc(udps
, (nudps
+1)*sizeof(ivl_udp_t
));
1178 udps
[nudps
++] = udp
;
1182 fprintf(vvp_out
, "L_%p .udp", lptr
);
1183 fprintf(vvp_out
, " UDP_%s",
1184 vvp_mangle_id(ivl_udp_name(udp
)));
1187 for (pdx
= 1 ; pdx
< ivl_logic_pins(lptr
) ; pdx
+= 1) {
1188 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
);
1190 /* Unlike other logic gates, primitives may have unconnected
1191 inputs. The proper behavior is to attach a HiZ to the
1194 assert(ivl_logic_width(lptr
) == 1);
1195 fprintf(vvp_out
, ", C4<z>");
1198 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1202 fprintf(vvp_out
, ";\n");
1205 static void draw_logic_in_scope(ivl_net_logic_t lptr
)
1208 const char*ltype
= "?";
1209 const char*lcasc
= 0;
1210 char identity_val
= '0';
1212 int need_delay_flag
= ivl_logic_delay(lptr
,0)? 1 : 0;
1214 unsigned vector_width
= width_of_nexus(ivl_logic_pin(lptr
, 0));
1216 ivl_drive_t str0
, str1
;
1219 int ninp
= ivl_logic_pins(lptr
) - 1;
1220 typedef const char*const_charp
;
1221 const_charp
*input_strings
= calloc(ninp
, sizeof(const_charp
));
1223 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1) {
1224 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
+1);
1226 /* Only UDPs can have unconnected inputs. */
1227 assert(ivl_logic_type(lptr
) == IVL_LO_UDP
);
1228 input_strings
[pdx
] = 0;
1230 input_strings
[pdx
] = draw_net_input(nex
);
1234 switch (ivl_logic_type(lptr
)) {
1237 free(input_strings
);
1238 draw_udp_in_scope(lptr
);
1242 /* Draw bufz objects, but only if the gate cannot
1243 be elided. If I can elide it, then the
1244 draw_nex_input will take care of it for me. */
1245 ivl_nexus_ptr_t nptr
= ivl_logic_pin_ptr(lptr
,0);
1249 if (can_elide_bufz(lptr
, nptr
))
1255 case IVL_LO_PULLDOWN
:
1257 /* Skip pullup and pulldown objects. Things that have
1258 pull objects as inputs will instead generate the
1259 appropriate C<?> symbol. */
1260 free(input_strings
);
1341 fprintf(stderr
, "vvp.tgt: error: Unhandled logic type: %u\n",
1342 ivl_logic_type(lptr
));
1347 { ivl_nexus_t nex
= ivl_logic_pin(lptr
, 0);
1348 ivl_nexus_ptr_t nptr
= 0;
1350 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
1351 nptr
= ivl_nexus_ptr(nex
,idx
);
1352 if (ivl_nexus_ptr_log(nptr
) != lptr
)
1354 if (ivl_nexus_ptr_pin(nptr
) != 0)
1358 str0
= ivl_nexus_ptr_drive0(nptr
);
1359 str1
= ivl_nexus_ptr_drive1(nptr
);
1365 /* Get all the input label that I will use for parameters to
1366 the functor that I create later. */
1367 ninp
= ivl_logic_pins(lptr
) - 1;
1368 input_strings
= calloc(ninp
, sizeof(char*));
1369 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1)
1370 input_strings
[pdx
] = draw_net_input(ivl_logic_pin(lptr
, pdx
+1));
1373 ninp
= ivl_logic_pins(lptr
) - 1;
1376 for (inst
= 0; inst
< ninp
; inst
+= 4) {
1378 fprintf(vvp_out
, "L_%p/%d/%d .functor %s %u",
1379 lptr
, level
, inst
, lcasc
, vector_width
);
1381 fprintf(vvp_out
, "L_%p%s .functor %s %u",
1382 lptr
, need_delay_flag
? "/d" : "",
1383 ltype
, vector_width
);
1385 if (str0
!= IVL_DR_STRONG
|| str1
!= IVL_DR_STRONG
)
1386 fprintf(vvp_out
, " [%u %u]", str0
, str1
);
1389 for (pdx
= inst
; pdx
< ninp
&& pdx
< inst
+4 ; pdx
+= 1) {
1391 fprintf(vvp_out
, ", L_%p/%d/%d",
1392 lptr
, level
- 1, pdx
*4);
1394 fprintf(vvp_out
, ", %s", input_strings
[pdx
]);
1397 for ( ; pdx
< inst
+4 ; pdx
+= 1) {
1399 fprintf(vvp_out
, ", C4<");
1400 for (wdx
= 0 ; wdx
< vector_width
; wdx
+= 1)
1401 fprintf(vvp_out
, "%c", identity_val
);
1402 fprintf(vvp_out
, ">");
1405 fprintf(vvp_out
, ";\n");
1408 ninp
= (ninp
+3) / 4;
1414 /* Free the array of char*. The strings themselves are
1415 persistent, held by the ivl_nexus_t objects. */
1416 free(input_strings
);
1418 /* If there are delays, then draw the delay functor to carry
1419 that delay. This is the final output. */
1420 if (need_delay_flag
) {
1421 ivl_expr_t rise_exp
= ivl_logic_delay(lptr
,0);
1422 ivl_expr_t fall_exp
= ivl_logic_delay(lptr
,1);
1423 ivl_expr_t decay_exp
= ivl_logic_delay(lptr
,2);
1425 if (number_is_immediate(rise_exp
,64)
1426 && number_is_immediate(fall_exp
,64)
1427 && number_is_immediate(decay_exp
,64)) {
1429 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1430 lptr
, get_number_immediate(rise_exp
),
1431 get_number_immediate(rise_exp
),
1432 get_number_immediate(rise_exp
), lptr
);
1435 assert(ivl_expr_type(rise_exp
) == IVL_EX_SIGNAL
);
1436 assert(ivl_expr_type(fall_exp
) == IVL_EX_SIGNAL
);
1437 assert(ivl_expr_type(decay_exp
) == IVL_EX_SIGNAL
);
1439 fprintf(vvp_out
, "L_%p .delay L_%p/d", lptr
, lptr
);
1441 sig
= ivl_expr_signal(rise_exp
);
1442 assert(ivl_signal_array_count(sig
) == 1);
1443 fprintf(vvp_out
, ", v%p_0", sig
);
1445 sig
= ivl_expr_signal(fall_exp
);
1446 assert(ivl_signal_array_count(sig
) == 1);
1447 fprintf(vvp_out
, ", v%p_0", sig
);
1449 sig
= ivl_expr_signal(decay_exp
);
1450 assert(ivl_signal_array_count(sig
) == 1);
1451 fprintf(vvp_out
, ", v%p_0;\n", sig
);
1456 static void draw_event_in_scope(ivl_event_t obj
)
1458 unsigned nany
= ivl_event_nany(obj
);
1459 unsigned nneg
= ivl_event_nneg(obj
);
1460 unsigned npos
= ivl_event_npos(obj
);
1464 /* Figure out how many probe functors are needed. */
1466 cnt
+= (nany
+3) / 4;
1469 cnt
+= (nneg
+3) / 4;
1472 cnt
+= (npos
+3) / 4;
1475 /* If none are needed, then this is a named event. The
1476 code needed is easy. */
1477 fprintf(vvp_out
, "E_%p .event \"%s\";\n", obj
,
1478 vvp_mangle_name(ivl_event_basename(obj
)));
1480 } else if (cnt
> 1) {
1481 /* There are a bunch of events that need to be event/or
1486 for (idx
= 0 ; idx
< nany
; idx
+= 4, ecnt
+= 1) {
1489 fprintf(vvp_out
, "E_%p/%u .event edge", obj
, ecnt
);
1494 for (sub
= idx
; sub
< top
; sub
+= 1) {
1495 ivl_nexus_t nex
= ivl_event_any(obj
, sub
);
1496 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1498 fprintf(vvp_out
, ";\n");
1501 for (idx
= 0 ; idx
< nneg
; idx
+= 4, ecnt
+= 1) {
1504 fprintf(vvp_out
, "E_%p/%u .event negedge", obj
, ecnt
);
1509 for (sub
= idx
; sub
< top
; sub
+= 1) {
1510 ivl_nexus_t nex
= ivl_event_neg(obj
, sub
);
1511 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1513 fprintf(vvp_out
, ";\n");
1516 for (idx
= 0 ; idx
< npos
; idx
+= 4, ecnt
+= 1) {
1519 fprintf(vvp_out
, "E_%p/%u .event posedge", obj
, ecnt
);
1524 for (sub
= idx
; sub
< top
; sub
+= 1) {
1525 ivl_nexus_t nex
= ivl_event_pos(obj
, sub
);
1526 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1528 fprintf(vvp_out
, ";\n");
1531 assert(ecnt
== cnt
);
1533 fprintf(vvp_out
, "E_%p .event/or", obj
);
1534 fprintf(vvp_out
, " E_%p/0", obj
);
1536 for (idx
= 1 ; idx
< cnt
; idx
+= 1)
1537 fprintf(vvp_out
, ", E_%p/%u", obj
, idx
);
1539 fprintf(vvp_out
, ";\n");
1542 unsigned num_input_strings
= nany
+ nneg
+ npos
;
1544 ivl_nexus_t input_nexa
[4];
1545 const char*edge
= 0;
1547 assert(num_input_strings
<= 4);
1550 assert((nneg
+ npos
) == 0);
1555 for (idx
= 0 ; idx
< nany
; idx
+= 1) {
1556 ivl_nexus_t nex
= ivl_event_any(obj
, idx
);
1557 input_nexa
[idx
] = nex
;
1560 } else if (nneg
> 0) {
1561 assert((nany
+ npos
) == 0);
1564 for (idx
= 0 ; idx
< nneg
; idx
+= 1) {
1565 ivl_nexus_t nex
= ivl_event_neg(obj
, idx
);
1566 input_nexa
[idx
] = nex
;
1570 assert((nany
+ nneg
) == 0);
1573 for (idx
= 0 ; idx
< npos
; idx
+= 1) {
1574 ivl_nexus_t nex
= ivl_event_pos(obj
, idx
);
1575 input_nexa
[idx
] = nex
;
1579 fprintf(vvp_out
, "E_%p .event %s", obj
, edge
);
1580 for (idx
= 0 ; idx
< num_input_strings
; idx
+= 1)
1581 fprintf(vvp_out
, ", %s", draw_input_from_net(input_nexa
[idx
]));
1583 fprintf(vvp_out
, ";\n");
1588 * This function draws any functors needed to calculate the input to
1589 * this nexus, and leaves in the data array strings that can be used
1590 * as functor arguments. The strings are from the draw_net_input
1591 * function, which in turn returns nexus names, so the strings are
1592 * safe to pass around.
1594 static void draw_lpm_data_inputs(ivl_lpm_t net
, unsigned base
,
1595 unsigned ndata
, const char**src_table
)
1598 for (idx
= 0 ; idx
< ndata
; idx
+= 1) {
1599 ivl_nexus_t nex
= ivl_lpm_data(net
, base
+idx
);
1600 src_table
[idx
] = draw_net_input(nex
);
1604 static void draw_lpm_add(ivl_lpm_t net
)
1606 const char*src_table
[2];
1608 const char*type
= "";
1609 ivl_variable_type_t dta
= data_type_of_nexus(ivl_lpm_data(net
,0));
1610 ivl_variable_type_t dtb
= data_type_of_nexus(ivl_lpm_data(net
,1));
1611 ivl_variable_type_t dto
= IVL_VT_LOGIC
;
1613 if (dta
== IVL_VT_REAL
&& dtb
== IVL_VT_REAL
)
1616 width
= ivl_lpm_width(net
);
1618 switch (ivl_lpm_type(net
)) {
1623 if (dto
== IVL_VT_REAL
)
1631 case IVL_LPM_DIVIDE
:
1632 if (dto
== IVL_VT_REAL
)
1634 else if (ivl_lpm_signed(net
))
1646 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1647 fprintf(vvp_out
, "L_%p .arith/%s %u, %s, %s;\n",
1648 net
, type
, width
, src_table
[0], src_table
[1]);
1652 * The read port to an array is generated as a single record that takes
1653 * the address as an input.
1655 static void draw_lpm_array(ivl_lpm_t net
)
1658 ivl_signal_t mem
= ivl_lpm_array(net
);
1660 fprintf(vvp_out
, "L_%p .array/port v%p, ", net
, mem
);
1662 nex
= ivl_lpm_select(net
);
1663 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1665 fprintf(vvp_out
, ";\n");
1668 static void draw_lpm_cmp(ivl_lpm_t net
)
1670 const char*src_table
[2];
1672 const char*type
= "";
1673 const char*signed_string
= ivl_lpm_signed(net
)? ".s" : "";
1675 width
= ivl_lpm_width(net
);
1677 switch (ivl_lpm_type(net
)) {
1678 case IVL_LPM_CMP_EEQ
:
1682 case IVL_LPM_CMP_EQ
:
1686 case IVL_LPM_CMP_GE
:
1689 case IVL_LPM_CMP_GT
:
1692 case IVL_LPM_CMP_NE
:
1696 case IVL_LPM_CMP_NEE
:
1704 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1705 fprintf(vvp_out
, "L_%p .cmp/%s%s %u, %s, %s;\n",
1706 net
, type
, signed_string
, width
,
1707 src_table
[0], src_table
[1]);
1711 * This function draws the arguments to a .const node using the
1712 * lpm inputs starting at "start" and for "cnt" inputs. This input
1713 * count must be <= 4. It is up to the caller to write the header part
1714 * of the statement, and to organize the data into multiple
1717 * Return the width of the final concatenation.
1719 static unsigned lpm_concat_inputs(ivl_lpm_t net
, unsigned start
,
1720 unsigned cnt
, const char*src_table
[])
1727 /* First, draw the [L M N O] part of the statement, the list
1728 of widths for the .concat statement. */
1729 fprintf(vvp_out
, "[");
1731 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1732 ivl_nexus_t nex
= ivl_lpm_data(net
, start
+idx
);
1733 unsigned nexus_width
= width_of_nexus(nex
);
1734 fprintf(vvp_out
, " %u", nexus_width
);
1738 for ( ; idx
< 4 ; idx
+= 1)
1739 fprintf(vvp_out
, " 0");
1741 fprintf(vvp_out
, "]");
1744 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1745 fprintf(vvp_out
, ", %s", src_table
[idx
]);
1748 fprintf(vvp_out
, ";\n");
1753 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1754 * many nested nodes as necessary to support the desired number of
1757 static void draw_lpm_concat(ivl_lpm_t net
)
1759 const char*src_table
[4];
1760 unsigned icnt
= ivl_lpm_selects(net
);
1763 /* This is the easiest case. There are 4 or fewer input
1764 vectors, so the entire IVL_LPM_CONCAT can be
1765 implemented with a single .concat node. */
1766 draw_lpm_data_inputs(net
, 0, icnt
, src_table
);
1767 fprintf(vvp_out
, "L_%p .concat ", net
);
1768 lpm_concat_inputs(net
, 0, icnt
, src_table
);
1771 /* If there are more than 4 inputs, things get more
1772 complicated. We need to generate a balanced tree of
1773 .concat nodes to blend the inputs down to a single
1774 root node, that becomes the output from the
1776 unsigned idx
, depth
;
1777 struct concat_tree
{
1782 tree
= malloc((icnt
+ 3)/4 * sizeof(struct concat_tree
));
1784 /* First, fill in all the leaves with the initial inputs
1785 to the tree. After this loop, there are (icnt+3)/4
1786 .concat nodes drawn, that together take all the
1788 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1791 if ((idx
+ trans
) > icnt
)
1794 draw_lpm_data_inputs(net
, idx
, trans
, src_table
);
1795 fprintf(vvp_out
, "LS_%p_0_%u .concat ", net
, idx
);
1796 wid
= lpm_concat_inputs(net
, idx
, trans
, src_table
);
1798 tree
[idx
/4].base
= idx
;
1799 tree
[idx
/4].wid
= wid
;
1802 /* icnt is the input count for the level. It is the
1803 number of .concats of the previous level that have to
1804 be concatenated at the current level. (This is not
1805 the same as the bit width.) */
1806 icnt
= (icnt
+ 3)/4;
1808 /* Tree now has icnt nodes that are depth=0 concat nodes
1809 which take in the leaf inputs. The while loop below
1810 starts and ends with a tree of icnt nodes. Each time
1811 through, there are 1/4 the nodes we started
1812 with. Thus, we eventually get down to <=4 nodes, and
1813 that is when we fall out of the loop. */
1817 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1821 if ((idx
+trans
) > icnt
)
1824 fprintf(vvp_out
, "LS_%p_%u_%u .concat [",
1827 for (tdx
= 0 ; tdx
< trans
; tdx
+= 1) {
1828 fprintf(vvp_out
, " %u", tree
[idx
+tdx
].wid
);
1829 wid
+= tree
[idx
+tdx
].wid
;
1832 for ( ; tdx
< 4 ; tdx
+= 1)
1833 fprintf(vvp_out
, " 0");
1835 fprintf(vvp_out
, "]");
1837 for (tdx
= 0; tdx
< trans
; tdx
+= 1) {
1838 fprintf(vvp_out
, ", LS_%p_%u_%u", net
,
1839 depth
-1, tree
[idx
+tdx
].base
);
1842 fprintf(vvp_out
, ";\n");
1843 tree
[idx
/4].base
= idx
;
1844 tree
[idx
/4].wid
= wid
;
1848 icnt
= (icnt
+ 3)/4;
1851 /* Finally, draw the root node that takes in the final
1852 row of tree nodes and generates a single output. */
1853 fprintf(vvp_out
, "L_%p .concat [", net
);
1854 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1855 fprintf(vvp_out
, " %u", tree
[idx
].wid
);
1856 for ( ; idx
< 4 ; idx
+= 1)
1857 fprintf(vvp_out
, " 0");
1858 fprintf(vvp_out
, "]");
1860 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
1861 fprintf(vvp_out
, ", LS_%p_%u_%u",
1862 net
, depth
-1, tree
[idx
].base
);
1864 fprintf(vvp_out
, ";\n");
1870 * primitive FD (q, clk, ce, d);
1875 * // clk ce d r s q q+
1876 * r 1 0 0 0 : ? : 0;
1877 * r 1 1 0 0 : ? : 1;
1878 * f 1 ? 0 0 : ? : -;
1879 * ? 1 ? 0 0 : ? : -;
1880 * * 0 ? 0 0 : ? : -;
1881 * ? ? ? 1 ? : ? : 0;
1882 * ? ? ? 0 1 : ? : 1;
1886 static void draw_lpm_ff(ivl_lpm_t net
)
1888 ivl_expr_t aset_expr
= 0;
1889 const char*aset_bits
= 0;
1894 width
= ivl_lpm_width(net
);
1896 aset_expr
= ivl_lpm_aset_value(net
);
1898 assert(ivl_expr_width(aset_expr
) == width
);
1899 aset_bits
= ivl_expr_bits(aset_expr
);
1903 fprintf(vvp_out
, "L_%p .dff ", net
);
1905 nex
= ivl_lpm_data(net
,0);
1907 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1909 nex
= ivl_lpm_clk(net
);
1911 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1913 nex
= ivl_lpm_enable(net
);
1915 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1917 fprintf(vvp_out
, ", C4<1>");
1920 /* Stub asynchronous input for now. */
1921 fprintf(vvp_out
, ", C4<z>");
1923 fprintf(vvp_out
, ";\n");
1926 static void draw_lpm_shiftl(ivl_lpm_t net
)
1928 unsigned width
= ivl_lpm_width(net
);
1929 const char* signed_flag
= ivl_lpm_signed(net
)? "s" : "";
1931 if (ivl_lpm_type(net
) == IVL_LPM_SHIFTR
)
1932 fprintf(vvp_out
, "L_%p .shift/r%s %u", net
, signed_flag
, width
);
1934 fprintf(vvp_out
, "L_%p .shift/l %u", net
, width
);
1936 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 0)));
1938 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 1)));
1940 fprintf(vvp_out
, ";\n");
1943 static void draw_type_string_of_nex(ivl_nexus_t nex
)
1945 switch (data_type_of_nexus(nex
)) {
1947 fprintf(vvp_out
, "r");
1951 fprintf(vvp_out
, "v%d", width_of_nexus(nex
));
1959 static void draw_lpm_sfunc(ivl_lpm_t net
)
1962 fprintf(vvp_out
, "L_%p .sfunc \"%s\"", net
, ivl_lpm_string(net
));
1964 /* Print the function type descriptor string. */
1965 fprintf(vvp_out
, ", \"");
1967 draw_type_string_of_nex(ivl_lpm_q(net
,0));
1969 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1)
1970 draw_type_string_of_nex(ivl_lpm_data(net
,idx
));
1972 fprintf(vvp_out
, "\"");
1974 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
1975 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
,idx
)));
1978 fprintf(vvp_out
, ";\n");
1981 static void draw_lpm_ufunc(ivl_lpm_t net
)
1984 ivl_scope_t def
= ivl_lpm_define(net
);
1986 fprintf(vvp_out
, "L_%p .ufunc TD_%s, %u", net
,
1987 ivl_scope_name(def
),
1988 ivl_lpm_width(net
));
1990 /* Print all the net signals that connect to the input of the
1992 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
1993 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, idx
)));
1997 assert((ivl_lpm_size(net
)+1) == ivl_scope_ports(def
));
1999 /* Now print all the variables in the function scope that
2000 receive the input values given in the previous list. */
2001 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2002 ivl_signal_t psig
= ivl_scope_port(def
, idx
+1);
2005 fprintf(vvp_out
, " (");
2007 fprintf(vvp_out
, ", ");
2009 assert(ivl_signal_array_count(psig
) == 1);
2010 fprintf(vvp_out
, "v%p_0", psig
);
2013 fprintf(vvp_out
, ")");
2015 /* Finally, print the reference to the signal from which the
2016 result is collected. */
2017 { ivl_signal_t psig
= ivl_scope_port(def
, 0);
2018 assert(ivl_lpm_width(net
) == ivl_signal_width(psig
));
2019 assert(ivl_signal_array_count(psig
) == 1);
2021 fprintf(vvp_out
, " v%p_0", psig
);
2024 fprintf(vvp_out
, ";\n");
2028 * Handle a PART SELECT device. This has a single input and output,
2029 * plus an optional extra input that is a non-constant base.
2031 static void draw_lpm_part(ivl_lpm_t net
)
2033 unsigned width
, base
;
2036 width
= ivl_lpm_width(net
);
2037 base
= ivl_lpm_base(net
);
2038 sel
= ivl_lpm_data(net
,1);
2041 fprintf(vvp_out
, "L_%p .part %s",
2042 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2043 fprintf(vvp_out
, ", %u, %u;\n", base
, width
);
2045 fprintf(vvp_out
, "L_%p .part/v %s",
2046 net
, draw_net_input(ivl_lpm_data(net
,0)));
2047 fprintf(vvp_out
, ", %s", draw_net_input(sel
));
2048 fprintf(vvp_out
, ", %u;\n", width
);
2053 * Handle a PART SELECT PV device. Generate a .part/pv node that
2054 * includes the part input, and the geometry of the part.
2056 static void draw_lpm_part_pv(ivl_lpm_t net
)
2058 unsigned width
= ivl_lpm_width(net
);
2059 unsigned base
= ivl_lpm_base(net
);
2060 unsigned signal_width
= width_of_nexus(ivl_lpm_q(net
,0));
2062 fprintf(vvp_out
, "L_%p .part/pv %s",
2063 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2065 fprintf(vvp_out
, ", %u, %u, %u;\n", base
, width
, signal_width
);
2069 * Handle the drawing of a bi-directional part select. The two ports
2070 * are simultaneously input and output. A simple minded connect of the
2071 * input to the output causes a functor cycle which will lock into an
2072 * X value, so something special is needed.
2074 * NOTE: The inputs of the tran device at this point need to be from
2075 * all the drivers of the nexus *except* the tran itself. This
2076 * function will draw three labels that can be linked:
2078 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2079 * ivl_lpm_data, the tran acts like a forward part select in that
2082 * The device creates these nodes:
2085 * This is the Q port of the tran resolved and padded to the maximum
2086 * width of the tran. The tran itself is not included in the
2087 * resolution of this port.
2090 * This is the Q and D parts resolved together, still without the tran
2094 * This is the /V node part-selected back to the dimensions of the Q
2097 static void draw_lpm_part_bi(ivl_lpm_t net
)
2099 unsigned width
= ivl_lpm_width(net
);
2100 unsigned base
= ivl_lpm_base(net
);
2101 unsigned signal_width
= width_of_nexus(ivl_lpm_data(net
,0));
2105 ivl_nexus_ptr_t ptr
= 0;
2110 /* It seems implausible that the two inputs of a tran will be
2111 connected together. So assert that this is so to simplify
2112 the code to look for the nexus_ptr_t objects. */
2113 assert(ivl_lpm_q(net
,0) != ivl_lpm_data(net
,0));
2115 nex
= ivl_lpm_q(net
,0);
2116 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2117 ptr
= ivl_nexus_ptr(nex
, idx
);
2118 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2122 p_str
= draw_net_input_x(nex
, ptr
, 0, 0);
2124 nex
= ivl_lpm_data(net
,0);
2125 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2126 ptr
= ivl_nexus_ptr(nex
, idx
);
2127 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2130 v_str
= draw_net_input_x(nex
, ptr
, OMIT_PART_BI_DATA
, 0);
2132 /* Pad the part-sized input out to a common width...
2133 The /i label is the Q side of the tran, resolved except for
2134 the tran itself and padded (with z) to the larger width. */
2135 fprintf(vvp_out
, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2136 net
, p_str
, base
, width
, signal_width
);
2138 /* Resolve together the two halves of the tran...
2139 The /V label is the ports of the tran (now the same width)
2140 resolved together. Neither input to this resolver includes
2142 fprintf(vvp_out
, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2145 /* The full-width side is created by the tran device, all we
2146 have left to to is take a part select of that for the
2147 smaller output, and this becomes the part select output of
2149 fprintf(vvp_out
, "L_%p/P .part L_%p/V, %u, %u;\n", net
,
2157 * Draw unary reduction devices.
2159 static void draw_lpm_re(ivl_lpm_t net
, const char*type
)
2161 fprintf(vvp_out
, "L_%p .reduce/%s %s;\n",
2162 net
, type
, draw_net_input(ivl_lpm_data(net
,0)));
2165 static void draw_lpm_repeat(ivl_lpm_t net
)
2167 fprintf(vvp_out
, "L_%p .repeat %u, %u, %s;\n", net
,
2168 ivl_lpm_width(net
), ivl_lpm_size(net
),
2169 draw_net_input(ivl_lpm_data(net
,0)));
2172 static void draw_lpm_sign_ext(ivl_lpm_t net
)
2174 fprintf(vvp_out
, "L_%p .extend/s %u, %s;\n",
2175 net
, ivl_lpm_width(net
),
2176 draw_net_input(ivl_lpm_data(net
,0)));
2179 static void draw_lpm_in_scope(ivl_lpm_t net
)
2181 switch (ivl_lpm_type(net
)) {
2186 case IVL_LPM_DIVIDE
:
2192 draw_lpm_array(net
);
2195 case IVL_LPM_PART_BI
:
2196 draw_lpm_part_bi(net
);
2199 case IVL_LPM_PART_VP
:
2203 case IVL_LPM_PART_PV
:
2204 draw_lpm_part_pv(net
);
2207 case IVL_LPM_CONCAT
:
2208 draw_lpm_concat(net
);
2215 case IVL_LPM_CMP_EEQ
:
2216 case IVL_LPM_CMP_EQ
:
2217 case IVL_LPM_CMP_GE
:
2218 case IVL_LPM_CMP_GT
:
2219 case IVL_LPM_CMP_NE
:
2220 case IVL_LPM_CMP_NEE
:
2228 case IVL_LPM_RE_AND
:
2229 draw_lpm_re(net
, "and");
2232 draw_lpm_re(net
, "or");
2234 case IVL_LPM_RE_XOR
:
2235 draw_lpm_re(net
, "xor");
2237 case IVL_LPM_RE_NAND
:
2238 draw_lpm_re(net
, "nand");
2240 case IVL_LPM_RE_NOR
:
2241 draw_lpm_re(net
, "nor");
2243 case IVL_LPM_RE_XNOR
:
2244 draw_lpm_re(net
, "xnor");
2247 case IVL_LPM_REPEAT
:
2248 draw_lpm_repeat(net
);
2251 case IVL_LPM_SHIFTL
:
2252 case IVL_LPM_SHIFTR
:
2253 draw_lpm_shiftl(net
);
2256 case IVL_LPM_SIGN_EXT
:
2257 draw_lpm_sign_ext(net
);
2261 draw_lpm_sfunc(net
);
2265 draw_lpm_ufunc(net
);
2269 fprintf(stderr
, "XXXX LPM not supported: %s.%s\n",
2270 ivl_scope_name(ivl_lpm_scope(net
)), ivl_lpm_basename(net
));
2274 int draw_scope(ivl_scope_t net
, ivl_scope_t parent
)
2278 switch (ivl_scope_type(net
)) {
2279 case IVL_SCT_MODULE
: type
= "module"; break;
2280 case IVL_SCT_FUNCTION
: type
= "function"; break;
2281 case IVL_SCT_TASK
: type
= "task"; break;
2282 case IVL_SCT_BEGIN
: type
= "begin"; break;
2283 case IVL_SCT_FORK
: type
= "fork"; break;
2284 case IVL_SCT_GENERATE
: type
= "generate"; break;
2285 default: type
= "?"; assert(0);
2288 fprintf(vvp_out
, "S_%p .scope %s, \"%s\" \"%s\"",
2289 net
, type
, vvp_mangle_name(ivl_scope_basename(net
)),
2290 ivl_scope_tname(net
));
2293 fprintf(vvp_out
, ", S_%p;\n", parent
);
2296 fprintf(vvp_out
, ";\n");
2299 fprintf(vvp_out
, " .timescale %d %d;\n", ivl_scope_time_units(net
),
2300 ivl_scope_time_precision(net
));
2302 for (idx
= 0 ; idx
< ivl_scope_params(net
) ; idx
+= 1) {
2303 ivl_parameter_t par
= ivl_scope_param(net
, idx
);
2304 ivl_expr_t pex
= ivl_parameter_expr(par
);
2305 switch (ivl_expr_type(pex
)) {
2307 fprintf(vvp_out
, "P_%p .param/str \"%s\", \"%s\";\n",
2308 par
, ivl_parameter_basename(par
),
2309 ivl_expr_string(pex
));
2312 fprintf(vvp_out
, "P_%p .param/l \"%s\", %sC4<",
2313 par
, ivl_parameter_basename(par
),
2314 ivl_expr_signed(pex
)? "+":"");
2315 { const char*bits
= ivl_expr_bits(pex
);
2316 unsigned nbits
= ivl_expr_width(pex
);
2318 for (bb
= 0 ; bb
< nbits
; bb
+= 1)
2319 fprintf(vvp_out
, "%c", bits
[nbits
-bb
-1]);
2321 fprintf(vvp_out
, ">;\n");
2324 fprintf(vvp_out
, "; parameter type %d unsupported\n",
2325 ivl_expr_type(pex
));
2330 /* Scan the scope for logic devices. For each device, draw out
2331 a functor that connects pin 0 to the output, and the
2332 remaining pins to inputs. */
2334 for (idx
= 0 ; idx
< ivl_scope_logs(net
) ; idx
+= 1) {
2335 ivl_net_logic_t lptr
= ivl_scope_log(net
, idx
);
2336 draw_logic_in_scope(lptr
);
2340 /* Scan the signals (reg and net) and draw the appropriate
2341 statements to make the signal function. */
2343 for (idx
= 0 ; idx
< ivl_scope_sigs(net
) ; idx
+= 1) {
2344 ivl_signal_t sig
= ivl_scope_sig(net
, idx
);
2346 switch (ivl_signal_type(sig
)) {
2348 draw_reg_in_scope(sig
);
2351 draw_net_in_scope(sig
);
2356 for (idx
= 0 ; idx
< ivl_scope_events(net
) ; idx
+= 1) {
2357 ivl_event_t event
= ivl_scope_event(net
, idx
);
2358 draw_event_in_scope(event
);
2361 for (idx
= 0 ; idx
< ivl_scope_lpms(net
) ; idx
+= 1) {
2362 ivl_lpm_t lpm
= ivl_scope_lpm(net
, idx
);
2363 draw_lpm_in_scope(lpm
);
2366 if (ivl_scope_type(net
) == IVL_SCT_TASK
)
2367 draw_task_definition(net
);
2369 if (ivl_scope_type(net
) == IVL_SCT_FUNCTION
)
2370 draw_func_definition(net
);
2372 ivl_scope_children(net
, (ivl_scope_f
*) draw_scope
, net
);