2 * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 # include "vvp_priv.h"
27 # include <inttypes.h>
30 struct vvp_nexus_data
{
31 /* draw_net_input uses this */
33 unsigned drivers_count
;
35 /* draw_net_in_scope uses these to identify the controlling word. */
39 #define VVP_NEXUS_DATA_STR 0x0001
42 static struct vvp_nexus_data
*new_nexus_data()
44 struct vvp_nexus_data
*data
= calloc(1, sizeof(struct vvp_nexus_data
));
49 * Escape non-symbol characters in ids, and quotes in strings.
52 inline static char hex_digit(unsigned i
)
55 return i
>=10 ? i
-10+'A' : i
+'0';
58 const char *vvp_mangle_id(const char *id
)
60 static char *out
= 0x0;
61 static size_t out_len
;
67 const char nosym
[] = "!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~";
69 char *se
= strpbrk(inp
, nosym
);
75 unsigned int nlen
= strlen(id
) + 4*(++nesc
) + 1;
77 out
= realloc(out
, nlen
);
82 strncpy(out
+iout
, inp
, n
);
96 out
[iout
++] = hex_digit(*se
>> 4);
97 out
[iout
++] = hex_digit(*se
);
101 se
= strpbrk(inp
, nosym
);
104 strcpy(out
+iout
, inp
);
108 const char *vvp_mangle_name(const char *id
)
110 static char *out
= 0x0;
111 static size_t out_len
;
115 const char *inp
= id
;
117 const char nosym
[] = "\"\\";
119 char *se
= strpbrk(inp
, nosym
);
125 unsigned int nlen
= strlen(id
) + 2*(++nesc
) + 1;
126 if (out_len
< nlen
) {
127 out
= realloc(out
, nlen
);
132 strncpy(out
+iout
, inp
, n
);
139 se
= strpbrk(inp
, nosym
);
142 strcpy(out
+iout
, inp
);
146 static void draw_C4_repeated_constant(char bit_char
, unsigned width
)
150 fprintf(vvp_out
, "C4<");
151 for (idx
= 0 ; idx
< width
; idx
+= 1)
152 fprintf(vvp_out
, "%c", bit_char
);
154 fprintf(vvp_out
, ">");
157 static void str_repeat(char*buf
, const char*str
, unsigned rpt
)
160 size_t len
= strlen(str
);
161 for (idx
= 0 ; idx
< rpt
; idx
+= 1) {
167 /* REMOVE ME: vvp_signal_label should not be used. DEAD CODE
168 * Given a signal, generate a string name that is suitable for use as
169 * a label. The only rule is that the same signal will always have the
170 * same label. The result is stored in static memory, so remember to
173 const char* vvp_signal_label(ivl_signal_t sig
)
176 sprintf(buf
, "%p", sig
);
180 ivl_signal_t
signal_of_nexus(ivl_nexus_t nex
, unsigned*word
)
183 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
184 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
, idx
);
185 ivl_signal_t sig
= ivl_nexus_ptr_sig(ptr
);
188 if (ivl_signal_local(sig
))
190 *word
= ivl_nexus_ptr_pin(ptr
);
197 ivl_signal_type_t
signal_type_of_nexus(ivl_nexus_t nex
)
200 ivl_signal_type_t out
= IVL_SIT_TRI
;
202 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
203 ivl_signal_type_t stype
;
204 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
, idx
);
205 ivl_signal_t sig
= ivl_nexus_ptr_sig(ptr
);
209 stype
= ivl_signal_type(sig
);
210 if (stype
== IVL_SIT_REG
)
212 if (stype
== IVL_SIT_TRI
)
214 if (stype
== IVL_SIT_NONE
)
222 unsigned width_of_nexus(ivl_nexus_t nex
)
226 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
227 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
, idx
);
228 ivl_signal_t sig
= ivl_nexus_ptr_sig(ptr
);
230 return ivl_signal_width(sig
);
236 ivl_variable_type_t
data_type_of_nexus(ivl_nexus_t nex
)
239 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
240 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
, idx
);
241 ivl_signal_t sig
= ivl_nexus_ptr_sig(ptr
);
243 return ivl_signal_data_type(sig
);
246 /* shouldn't happen! */
247 return IVL_VT_NO_TYPE
;
251 ivl_nexus_ptr_t
ivl_logic_pin_ptr(ivl_net_logic_t net
, unsigned pin
)
253 ivl_nexus_t nex
= ivl_logic_pin(net
, pin
);
256 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
257 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
, idx
);
258 ivl_net_logic_t tmp
= ivl_nexus_ptr_log(ptr
);
263 if (ivl_nexus_ptr_pin(ptr
) != pin
)
272 const char*drive_string(ivl_drive_t drive
)
298 * The draw_scope function draws the major functional items within a
299 * scope. This includes the scopes themselves, of course. All the
300 * other functions in this file are in support of that task.
306 * ivl builds up the netlist into objects connected together by
307 * ivl_nexus_t objects. The nexus receives all the drivers of the
308 * point in the net and resolves the value. The result is then sent to
309 * all the nets that are connected to the nexus. The nets, then, are
310 * read to get the value of the nexus.
313 * Nets are interesting and special, because a nexus may be connected
314 * to several of them at once. This can happen, for example, as an
315 * artifact of module port connects, where the inside and the outside
316 * of the module are connected through an in-out port. (In fact, ivl
317 * will simply connect signals that are bound through a port, because
318 * the input/output/inout properties are enforced as compile time.)
320 * This case is handled by choosing one to receive the value of the
321 * nexus. This one then feeds to another net at the nexus, and so
322 * on. The last net is selected as the output of the nexus.
326 * This tests a bufz device against an output receiver, and determines
327 * if the device can be skipped. If this function returns true, then a
328 * gate will be generated for this node. Otherwise, the code generator
329 * will connect its input to its output and skip the gate.
331 static int can_elide_bufz(ivl_net_logic_t net
, ivl_nexus_ptr_t nptr
)
336 /* These are the drives we expect. */
337 ivl_drive_t dr0
= ivl_nexus_ptr_drive0(nptr
);
338 ivl_drive_t dr1
= ivl_nexus_ptr_drive1(nptr
);
341 /* If the gate carries a delay, it must remain. */
342 if (ivl_logic_delay(net
, 0) != 0)
345 /* If the input is connected to the output, then do not elide
346 the gate. This is some sort of cycle. */
347 if (ivl_logic_pin(net
, 0) == ivl_logic_pin(net
, 1))
350 in_n
= ivl_logic_pin(net
, 1);
351 for (idx
= 0 ; idx
< ivl_nexus_ptrs(in_n
) ; idx
+= 1) {
352 ivl_nexus_ptr_t in_np
= ivl_nexus_ptr(in_n
, idx
);
353 if (ivl_nexus_ptr_log(in_np
) == net
)
356 /* If the driver for the source does not match the
357 expected drive, then we need to keep the bufz. This
358 test also catches the case that the input device is
359 really also an input, as that device will have a
360 drive of HiZ. We need to keep BUFZ devices in that
361 case in order to prevent back-flow of data. */
362 if (ivl_nexus_ptr_drive0(in_np
) != dr0
)
364 if (ivl_nexus_ptr_drive1(in_np
) != dr1
)
370 /* If the BUFZ input has multiple drivers on its input, then
371 we need to keep this device in order to hide the
373 if (drive_count
!= 1)
380 * Given a nexus, look for a signal that has module delay
381 * paths. Return that signal. (There should be no more than 1.) If we
382 * don't find any, then return nil.
384 static ivl_signal_t
find_modpath(ivl_nexus_t nex
)
387 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
388 ivl_nexus_ptr_t ptr
= ivl_nexus_ptr(nex
,idx
);
389 ivl_signal_t sig
= ivl_nexus_ptr_sig(ptr
);
392 if (ivl_signal_npath(sig
) == 0)
401 static char* draw_C4_to_string(ivl_net_const_t cptr
)
403 const char*bits
= ivl_const_bits(cptr
);
406 size_t result_len
= 5 + ivl_const_width(cptr
);
407 char*result
= malloc(result_len
);
412 for (idx
= 0 ; idx
< ivl_const_width(cptr
) ; idx
+= 1) {
413 char bitchar
= bits
[ivl_const_width(cptr
)-idx
-1];
415 assert((dp
- result
) < result_len
);
422 static char* draw_C8_to_string(ivl_net_const_t cptr
,
423 ivl_drive_t dr0
, ivl_drive_t dr1
)
425 size_t nresult
= 5 + 3*ivl_const_width(cptr
);
426 char*result
= malloc(nresult
);
427 const char*bits
= ivl_const_bits(cptr
);
430 char dr0c
= "01234567"[dr0
];
431 char dr1c
= "01234567"[dr1
];
437 for (idx
= 0 ; idx
< ivl_const_width(cptr
) ; idx
+= 1) {
438 switch (bits
[ivl_const_width(cptr
)-idx
-1]) {
465 assert(dp
- result
< nresult
);
472 static char* draw_Cr_to_string(double value
)
480 snprintf(tmp
, sizeof(tmp
), "Cr<m0g3fff>");
482 snprintf(tmp
, sizeof(tmp
), "Cr<m0g7fff>");
493 double fract
= frexp(value
, &expo
);
494 fract
= ldexp(fract
, 63);
498 int vexp
= expo
+ 0x1000;
500 assert(vexp
< 0x2000);
503 snprintf(tmp
, sizeof(tmp
), "Cr<m%" PRIx64
"g%x>", mant
, vexp
);
508 * This function takes a nexus and looks for an input functor. It then
509 * draws to the output a string that represents that functor. What we
510 * are trying to do here is find the input to the net that is attached
514 static char* draw_net_input_drive(ivl_nexus_t nex
, ivl_nexus_ptr_t nptr
)
516 unsigned nptr_pin
= ivl_nexus_ptr_pin(nptr
);
517 ivl_net_const_t cptr
;
518 ivl_net_logic_t lptr
;
522 lptr
= ivl_nexus_ptr_log(nptr
);
523 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_BUFZ
) && (nptr_pin
== 0))
525 if (! can_elide_bufz(lptr
, nptr
))
528 return strdup(draw_net_input(ivl_logic_pin(lptr
, 1)));
531 /* If this is a pulldown device, then there is a single pin
532 that drives a constant value to the entire width of the
533 vector. The driver normally drives a pull0 value, so a C8<>
534 constant is appropriate, but if the drive is really strong,
535 then we can draw a C4<> constant instead. */
536 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_PULLDOWN
)) {
537 if (ivl_nexus_ptr_drive0(nptr
) == IVL_DR_STRONG
) {
538 size_t result_len
= ivl_logic_width(lptr
) + 5;
539 char*result
= malloc(result_len
);
543 str_repeat(dp
, "0", ivl_logic_width(lptr
));
544 dp
+= ivl_logic_width(lptr
);
547 assert((dp
-result
) <= result_len
);
551 size_t result_len
= 3*ivl_logic_width(lptr
) + 5;
552 char*result
= malloc(result_len
);
555 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
562 str_repeat(dp
, val
, ivl_logic_width(lptr
));
563 dp
+= 3*ivl_logic_width(lptr
);
566 assert((dp
-result
) <= result_len
);
571 if (lptr
&& (ivl_logic_type(lptr
) == IVL_LO_PULLUP
)) {
572 if (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_STRONG
) {
573 size_t result_len
= 5 + ivl_logic_width(lptr
);
574 char*result
= malloc(result_len
);
578 str_repeat(dp
, "1", ivl_logic_width(lptr
));
579 dp
+= ivl_logic_width(lptr
);
582 assert((dp
-result
) <= result_len
);
586 size_t result_len
= 5 + 3*ivl_logic_width(lptr
);
587 char*result
= malloc(result_len
);
590 val
[0] = "01234567"[ivl_nexus_ptr_drive0(nptr
)];
597 str_repeat(dp
, val
, ivl_logic_width(lptr
));
598 dp
+= 3*ivl_logic_width(lptr
);
601 assert((dp
-result
) <= result_len
);
606 if (lptr
&& (nptr_pin
== 0)) {
608 snprintf(tmp
, sizeof tmp
, "L_%p", lptr
);
612 sptr
= ivl_nexus_ptr_sig(nptr
);
613 if (sptr
&& (ivl_signal_type(sptr
) == IVL_SIT_REG
)) {
615 /* Input is a .var. This device may be a non-zero pin
616 because it may be an array of reg vectors. */
617 snprintf(tmp
, sizeof tmp
, "v%p_%u", sptr
, nptr_pin
);
621 cptr
= ivl_nexus_ptr_con(nptr
);
623 /* Constants should have exactly 1 pin, with a literal value. */
624 assert(nptr_pin
== 0);
627 switch (ivl_const_type(cptr
)) {
630 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_STRONG
)
631 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_STRONG
)) {
633 result
= draw_C4_to_string(cptr
);
636 result
= draw_C8_to_string(cptr
,
637 ivl_nexus_ptr_drive0(nptr
),
638 ivl_nexus_ptr_drive1(nptr
));
643 result
= draw_Cr_to_string(ivl_const_real(cptr
));
651 ivl_expr_t d_rise
= ivl_const_delay(cptr
, 0);
652 ivl_expr_t d_fall
= ivl_const_delay(cptr
, 1);
653 ivl_expr_t d_decay
= ivl_const_delay(cptr
, 2);
655 /* We have a delayed constant, so we need to build some code. */
657 assert(number_is_immediate(d_rise
, 64));
658 assert(number_is_immediate(d_fall
, 64));
659 assert(number_is_immediate(d_decay
, 64));
661 fprintf(vvp_out
, "L_%p/d .functor BUFZ 1, %s, "
662 "C4<0>, C4<0>, C4<0>;\n", cptr
, result
);
664 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
665 cptr
, get_number_immediate(d_rise
),
666 get_number_immediate(d_rise
),
667 get_number_immediate(d_rise
), cptr
);
671 snprintf(tmp
, sizeof tmp
, "L_%p", cptr
);
672 result
= strdup(tmp
);
678 lpm
= ivl_nexus_ptr_lpm(nptr
);
679 if (lpm
) switch (ivl_lpm_type(lpm
)) {
685 case IVL_LPM_CMP_EEQ
:
690 case IVL_LPM_CMP_NEE
:
694 case IVL_LPM_RE_NAND
:
696 case IVL_LPM_RE_XNOR
:
700 case IVL_LPM_SIGN_EXT
:
708 case IVL_LPM_PART_VP
:
709 case IVL_LPM_PART_PV
: /* NOTE: This is only a partial driver. */
711 if (ivl_lpm_q(lpm
, 0) == nex
) {
713 snprintf(tmp
, sizeof tmp
, "L_%p", lpm
);
718 case IVL_LPM_PART_BI
:
719 if (ivl_lpm_q(lpm
, 0) == nex
) {
721 snprintf(tmp
, sizeof tmp
, "L_%p/P", lpm
);
723 } else if (ivl_lpm_data(lpm
,0) == nex
) {
725 snprintf(tmp
, sizeof tmp
, "L_%p/V", lpm
);
731 fprintf(stderr
, "internal error: no input to nexus %s\n",
732 ivl_nexus_name(nex
));
734 return strdup("C<z>");
737 static int nexus_drive_is_strength_aware(ivl_nexus_ptr_t nptr
)
739 if (ivl_nexus_ptr_drive0(nptr
) != IVL_DR_STRONG
)
741 if (ivl_nexus_ptr_drive1(nptr
) != IVL_DR_STRONG
)
744 ivl_net_logic_t log
= ivl_nexus_ptr_log(nptr
);
746 /* These logic gates are able to generate unusual
747 strength values and so their outputs are considered
749 if (ivl_logic_type(log
) == IVL_LO_BUFIF0
)
751 if (ivl_logic_type(log
) == IVL_LO_BUFIF1
)
753 if (ivl_logic_type(log
) == IVL_LO_PMOS
)
755 if (ivl_logic_type(log
) == IVL_LO_NMOS
)
757 if (ivl_logic_type(log
) == IVL_LO_CMOS
)
765 * This function draws the input to a net into a string. What that
766 * means is that it returns a static string that can be used to
767 * represent a resolved driver to a nexus. If there are multiple
768 * drivers to the nexus, then it writes out the resolver declarations
769 * needed to perform strength resolution.
771 * The string that this returns is malloced, and that means that the
772 * caller must free the string or store it permanently. This function
773 * does *not* check for a previously calculated string. Use the
774 * draw_net_input for the general case.
776 /* Omit LPMPART_BI device pin-data(0) drivers. */
777 # define OMIT_PART_BI_DATA 0x0001
779 static char* draw_net_input_x(ivl_nexus_t nex
,
780 ivl_nexus_ptr_t omit_ptr
, int omit_flags
,
781 struct vvp_nexus_data
*nex_data
)
783 ivl_signal_type_t res
;
787 unsigned ndrivers
= 0;
788 static ivl_nexus_ptr_t
*drivers
= 0x0;
789 static unsigned adrivers
= 0;
791 const char*resolv_type
;
793 char*nex_private
= 0;
795 /* Accumulate nex_data flags. */
798 res
= signal_type_of_nexus(nex
);
804 resolv_type
= "tri0";
805 nex_flags
|= VVP_NEXUS_DATA_STR
;
808 resolv_type
= "tri1";
809 nex_flags
|= VVP_NEXUS_DATA_STR
;
812 resolv_type
= "triand";
815 resolv_type
= "trior";
818 fprintf(stderr
, "vvp.tgt: Unsupported signal type: %u\n", res
);
825 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
827 ivl_nexus_ptr_t nptr
= ivl_nexus_ptr(nex
, idx
);
829 /* If we are supposed to skip LPM_PART_BI data pins,
830 check that this driver is that. */
831 if ((omit_flags
&OMIT_PART_BI_DATA
)
832 && (lpm_tmp
= ivl_nexus_ptr_lpm(nptr
))
833 && (nex
== ivl_lpm_data(lpm_tmp
,0)))
836 if (nptr
== omit_ptr
)
839 /* Skip input only pins. */
840 if ((ivl_nexus_ptr_drive0(nptr
) == IVL_DR_HiZ
)
841 && (ivl_nexus_ptr_drive1(nptr
) == IVL_DR_HiZ
))
844 /* Mark the strength-aware flag if the driver can
845 generate values other than the standard "6"
847 if (nexus_drive_is_strength_aware(nptr
))
848 nex_flags
|= VVP_NEXUS_DATA_STR
;
850 /* Save this driver. */
851 if (ndrivers
>= adrivers
) {
853 drivers
= realloc(drivers
, adrivers
*sizeof(ivl_nexus_ptr_t
));
856 drivers
[ndrivers
] = nptr
;
860 /* If the caller is collecting nexus information, then save
861 the nexus driver count in the nex_data. */
863 nex_data
->drivers_count
= ndrivers
;
864 nex_data
->flags
|= nex_flags
;
867 /* If the nexus has no drivers, then send a constant HiZ into
870 unsigned idx
, wid
= width_of_nexus(nex
);
871 char*tmp
= malloc(wid
+ 5);
877 for (idx
= 0 ; idx
< wid
; idx
+= 1)
881 for (idx
= 0 ; idx
< wid
; idx
+= 1)
885 for (idx
= 0 ; idx
< wid
; idx
+= 1)
897 /* If the nexus has exactly one driver, then simply draw
898 it. Note that this will *not* work if the nexus is not a
900 if (ndrivers
== 1 && res
== IVL_SIT_TRI
) {
901 ivl_signal_t path_sig
= find_modpath(nex
);
903 char*nex_str
= draw_net_input_drive(nex
, drivers
[0]);
904 char modpath_label
[64];
905 snprintf(modpath_label
, sizeof modpath_label
,
907 nex_private
= strdup(modpath_label
);
908 draw_modpath(path_sig
, nex_str
);
911 nex_private
= draw_net_input_drive(nex
, drivers
[0]);
919 for (inst
= 0; inst
< ndrivers
; inst
+= 4) {
921 fprintf(vvp_out
, "RS_%p/%d/%d .resolv tri",
924 fprintf(vvp_out
, "RS_%p .resolv %s",
927 for (idx
= inst
; idx
< ndrivers
&& idx
< inst
+4; idx
+= 1) {
929 fprintf(vvp_out
, ", RS_%p/%d/%d",
930 nex
, level
- 1, idx
*4);
932 char*drive
= draw_net_input_drive(nex
, drivers
[idx
]);
933 fprintf(vvp_out
, ", %s", drive
);
937 for ( ; idx
< inst
+4 ; idx
+= 1) {
938 fprintf(vvp_out
, ", ");
939 draw_C4_repeated_constant('z',width_of_nexus(nex
));
942 fprintf(vvp_out
, ";\n");
945 ndrivers
= (ndrivers
+3) / 4;
951 sprintf(result
, "RS_%p", nex
);
952 nex_private
= strdup(result
);
957 * Get a cached description of the nexus input, or create one if this
958 * nexus has not been cached yet. This is a wrapper for the common
959 * case call to draw_net_input_x.
961 const char*draw_net_input(ivl_nexus_t nex
)
963 struct vvp_nexus_data
*nex_data
= (struct vvp_nexus_data
*)
964 ivl_nexus_get_private(nex
);
966 /* If this nexus already has a label, then its input is
967 already figured out. Just return the existing label. */
968 if (nex_data
&& nex_data
->net_input
)
969 return nex_data
->net_input
;
972 nex_data
= new_nexus_data();
973 ivl_nexus_set_private(nex
, nex_data
);
976 assert(nex_data
->net_input
== 0);
977 nex_data
->net_input
= draw_net_input_x(nex
, 0, 0, nex_data
);
979 return nex_data
->net_input
;
982 const char*draw_input_from_net(ivl_nexus_t nex
)
984 static char result
[32];
987 ivl_signal_t sig
= signal_of_nexus(nex
, &word
);
989 return draw_net_input(nex
);
991 snprintf(result
, sizeof result
, "v%p_%u", sig
, word
);
997 * This function draws a reg/int/variable in the scope. This is a very
998 * simple device to draw as there are no inputs to connect so no need
999 * to scan the nexus. We do have to account for the possibility that
1000 * the device is arrayed, though, by making a node for each array element.
1002 static void draw_reg_in_scope(ivl_signal_t sig
)
1004 int msb
= ivl_signal_msb(sig
);
1005 int lsb
= ivl_signal_lsb(sig
);
1007 const char*datatype_flag
= ivl_signal_integer(sig
) ? "/i" :
1008 ivl_signal_signed(sig
)? "/s" : "";
1009 const char*local_flag
= ivl_signal_local(sig
)? "*" : "";
1011 switch (ivl_signal_data_type(sig
)) {
1013 datatype_flag
= "/real";
1019 /* If the reg objects are collected into an array, then first
1020 write out the .array record to declare the array indices. */
1021 if (ivl_signal_dimensions(sig
) > 0) {
1022 unsigned word_count
= ivl_signal_array_count(sig
);
1023 int last
= ivl_signal_array_base(sig
)+word_count
-1;
1024 int first
= ivl_signal_array_base(sig
);
1025 fprintf(vvp_out
, "v%p .array%s \"%s\", %d %d, %d %d;\n",
1027 vvp_mangle_name(ivl_signal_basename(sig
)),
1028 last
, first
, msb
, lsb
);
1032 fprintf(vvp_out
, "v%p_0 .var%s %s\"%s\", %d %d;%s\n",
1033 sig
, datatype_flag
, local_flag
,
1034 vvp_mangle_name(ivl_signal_basename(sig
)), msb
, lsb
,
1035 ivl_signal_local(sig
)? " Local signal" : "");
1041 * This function draws a net. This is a bit more complicated as we
1042 * have to find an appropriate functor to connect to the input.
1044 static void draw_net_in_scope(ivl_signal_t sig
)
1046 int msb
= ivl_signal_msb(sig
);
1047 int lsb
= ivl_signal_lsb(sig
);
1049 const char*datatype_flag
= ivl_signal_signed(sig
)? "/s" : "";
1050 const char*local_flag
= ivl_signal_local(sig
)? "*" : "";
1053 switch (ivl_signal_data_type(sig
)) {
1055 datatype_flag
= "/real";
1061 for (iword
= 0 ; iword
< ivl_signal_array_count(sig
); iword
+= 1) {
1063 unsigned word_count
= ivl_signal_array_count(sig
);
1064 unsigned dimensions
= ivl_signal_dimensions(sig
);
1065 struct vvp_nexus_data
*nex_data
;
1067 /* Connect the pin of the signal to something. */
1068 ivl_nexus_t nex
= ivl_signal_nex(sig
, iword
);
1069 const char*driver
= draw_net_input(nex
);
1071 nex_data
= (struct vvp_nexus_data
*)ivl_nexus_get_private(nex
);
1074 if (nex_data
->net
== 0) {
1075 int strength_aware_flag
= 0;
1076 const char*vec8
= "";
1077 if (nex_data
->flags
&VVP_NEXUS_DATA_STR
)
1078 strength_aware_flag
= 1;
1079 if (nex_data
->drivers_count
> 1)
1081 if (strength_aware_flag
)
1084 if (iword
== 0 && dimensions
> 0) {
1085 int last
= ivl_signal_array_base(sig
) + word_count
-1;
1086 int first
= ivl_signal_array_base(sig
);
1087 fprintf(vvp_out
, "v%p .array \"%s\", %d %d;\n",
1088 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1091 if (dimensions
> 0) {
1092 /* If this is a word of an array, then use an
1093 array reference in place of the net name. */
1094 fprintf(vvp_out
, "v%p_%u .net%s%s v%p %u, %d %d, %s;"
1096 sig
, iword
, vec8
, datatype_flag
, sig
,
1097 iword
, msb
, lsb
, driver
,
1098 nex_data
->drivers_count
,
1099 strength_aware_flag
?", strength-aware":"");
1101 /* If this is an isolated word, it uses its
1103 assert(word_count
== 1);
1104 fprintf(vvp_out
, "v%p_%u .net%s%s %s\"%s\", %d %d, %s;"
1106 sig
, iword
, vec8
, datatype_flag
, local_flag
,
1107 vvp_mangle_name(ivl_signal_basename(sig
)),
1109 nex_data
->drivers_count
,
1110 strength_aware_flag
?", strength-aware":"");
1112 nex_data
->net
= sig
;
1113 nex_data
->net_word
= iword
;
1115 } else if (dimensions
> 0) {
1117 /* In this case, we have an alias to an existing
1118 signal array. this typically is an instance of
1119 port collapsing that the elaborator combined to
1120 discover that the entire array can be collapsed,
1121 so the word count for the signal and the alias
1124 if (word_count
== ivl_signal_array_count(nex_data
->net
)) {
1126 fprintf(vvp_out
, "v%p .array \"%s\", v%p; Alias to %s\n",
1127 sig
, vvp_mangle_name(ivl_signal_basename(sig
)),
1129 ivl_signal_basename(nex_data
->net
));
1131 /* An alias for an individual word. */
1134 int first
= ivl_signal_array_base(sig
);
1135 int last
= first
+ word_count
-1;
1136 fprintf(vvp_out
, "v%p .array \"%s\", %d %d;\n",
1138 vvp_mangle_name(ivl_signal_basename(sig
)),
1142 fprintf(vvp_out
, "v%p_%u .alias%s v%p %u, %d %d, "
1143 "v%p_%u; Alias to %s\n", sig
, iword
,
1144 datatype_flag
, sig
, iword
, msb
, lsb
,
1145 nex_data
->net
, nex_data
->net_word
,
1146 ivl_signal_basename(nex_data
->net
));
1149 /* Finally, we may have an alias that is a word
1150 connected to another word. Again, this is a
1151 case of port collapsing. */
1153 /* For the alias, create a different kind of node
1154 that refers to the alias source data instead of
1155 holding our own data. */
1156 fprintf(vvp_out
, "v%p_%u .alias%s \"%s\", %d %d, v%p_%u;\n",
1157 sig
, iword
, datatype_flag
,
1158 vvp_mangle_name(ivl_signal_basename(sig
)),
1159 msb
, lsb
, nex_data
->net
, nex_data
->net_word
);
1164 static void draw_delay(ivl_net_logic_t lptr
)
1166 ivl_expr_t d0
= ivl_logic_delay(lptr
, 0);
1167 ivl_expr_t d1
= ivl_logic_delay(lptr
, 1);
1168 ivl_expr_t d2
= ivl_logic_delay(lptr
, 2);
1170 if (d0
== 0 && d1
== 0 && d2
== 0)
1173 /* FIXME: Assume that the expression is a constant */
1174 assert(number_is_immediate(d0
, 64));
1175 assert(number_is_immediate(d1
, 64));
1176 assert(number_is_immediate(d2
, 64));
1178 if (d0
== d1
&& d1
== d2
)
1179 fprintf(vvp_out
, " (%lu)", get_number_immediate(d0
));
1181 fprintf(vvp_out
, " (%lu,%lu,%lu)",
1182 get_number_immediate(d0
),
1183 get_number_immediate(d1
),
1184 get_number_immediate(d2
));
1187 static void draw_udp_def(ivl_udp_t udp
)
1192 switch (ivl_udp_init(udp
))
1205 if (ivl_udp_sequ(udp
))
1207 "UDP_%s .udp/sequ \"%s\", %d, %d",
1208 vvp_mangle_id(ivl_udp_name(udp
)),
1209 vvp_mangle_name(ivl_udp_name(udp
)),
1214 "UDP_%s .udp/comb \"%s\", %d",
1215 vvp_mangle_id(ivl_udp_name(udp
)),
1216 vvp_mangle_name(ivl_udp_name(udp
)),
1219 for (i
=0; i
<ivl_udp_rows(udp
); i
++)
1220 fprintf(vvp_out
, "\n ,\"%s\"", ivl_udp_row(udp
, i
) );
1222 fprintf(vvp_out
, ";\n");
1225 static void draw_udp_in_scope(ivl_net_logic_t lptr
)
1229 ivl_udp_t udp
= ivl_logic_udp(lptr
);
1231 static ivl_udp_t
*udps
= 0x0;
1232 static int nudps
= 0;
1235 for (i
=0; i
<nudps
; i
++)
1241 udps
= realloc(udps
, (nudps
+1)*sizeof(ivl_udp_t
));
1243 udps
[nudps
++] = udp
;
1247 fprintf(vvp_out
, "L_%p .udp", lptr
);
1248 fprintf(vvp_out
, " UDP_%s",
1249 vvp_mangle_id(ivl_udp_name(udp
)));
1252 for (pdx
= 1 ; pdx
< ivl_logic_pins(lptr
) ; pdx
+= 1) {
1253 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
);
1255 /* Unlike other logic gates, primitives may have unconnected
1256 inputs. The proper behavior is to attach a HiZ to the
1259 assert(ivl_logic_width(lptr
) == 1);
1260 fprintf(vvp_out
, ", C4<z>");
1263 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
1267 fprintf(vvp_out
, ";\n");
1270 static void draw_logic_in_scope(ivl_net_logic_t lptr
)
1273 const char*ltype
= "?";
1274 const char*lcasc
= 0;
1275 char identity_val
= '0';
1277 int need_delay_flag
= ivl_logic_delay(lptr
,0)? 1 : 0;
1279 unsigned vector_width
= width_of_nexus(ivl_logic_pin(lptr
, 0));
1281 ivl_drive_t str0
, str1
;
1284 int ninp
= ivl_logic_pins(lptr
) - 1;
1285 typedef const char*const_charp
;
1286 const_charp
*input_strings
= calloc(ninp
, sizeof(const_charp
));
1288 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1) {
1289 ivl_nexus_t nex
= ivl_logic_pin(lptr
, pdx
+1);
1291 /* Only UDPs can have unconnected inputs. */
1292 assert(ivl_logic_type(lptr
) == IVL_LO_UDP
);
1293 input_strings
[pdx
] = 0;
1295 input_strings
[pdx
] = draw_net_input(nex
);
1299 switch (ivl_logic_type(lptr
)) {
1302 free(input_strings
);
1303 draw_udp_in_scope(lptr
);
1307 /* Draw bufz objects, but only if the gate cannot
1308 be elided. If I can elide it, then the
1309 draw_nex_input will take care of it for me. */
1310 ivl_nexus_ptr_t nptr
= ivl_logic_pin_ptr(lptr
,0);
1314 if (can_elide_bufz(lptr
, nptr
))
1320 case IVL_LO_PULLDOWN
:
1322 /* Skip pullup and pulldown objects. Things that have
1323 pull objects as inputs will instead generate the
1324 appropriate C<?> symbol. */
1325 free(input_strings
);
1406 fprintf(stderr
, "vvp.tgt: error: Unhandled logic type: %u\n",
1407 ivl_logic_type(lptr
));
1412 { ivl_nexus_t nex
= ivl_logic_pin(lptr
, 0);
1413 ivl_nexus_ptr_t nptr
= 0;
1415 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
1416 nptr
= ivl_nexus_ptr(nex
,idx
);
1417 if (ivl_nexus_ptr_log(nptr
) != lptr
)
1419 if (ivl_nexus_ptr_pin(nptr
) != 0)
1423 str0
= ivl_nexus_ptr_drive0(nptr
);
1424 str1
= ivl_nexus_ptr_drive1(nptr
);
1430 /* Get all the input label that I will use for parameters to
1431 the functor that I create later. */
1432 ninp
= ivl_logic_pins(lptr
) - 1;
1433 input_strings
= calloc(ninp
, sizeof(char*));
1434 for (pdx
= 0 ; pdx
< ninp
; pdx
+= 1)
1435 input_strings
[pdx
] = draw_net_input(ivl_logic_pin(lptr
, pdx
+1));
1438 ninp
= ivl_logic_pins(lptr
) - 1;
1441 for (inst
= 0; inst
< ninp
; inst
+= 4) {
1443 fprintf(vvp_out
, "L_%p/%d/%d .functor %s %u",
1444 lptr
, level
, inst
, lcasc
, vector_width
);
1446 fprintf(vvp_out
, "L_%p%s .functor %s %u",
1447 lptr
, need_delay_flag
? "/d" : "",
1448 ltype
, vector_width
);
1450 if (str0
!= IVL_DR_STRONG
|| str1
!= IVL_DR_STRONG
)
1451 fprintf(vvp_out
, " [%u %u]", str0
, str1
);
1454 for (pdx
= inst
; pdx
< ninp
&& pdx
< inst
+4 ; pdx
+= 1) {
1456 fprintf(vvp_out
, ", L_%p/%d/%d",
1457 lptr
, level
- 1, pdx
*4);
1459 fprintf(vvp_out
, ", %s", input_strings
[pdx
]);
1462 for ( ; pdx
< inst
+4 ; pdx
+= 1) {
1464 fprintf(vvp_out
, ", C4<");
1465 for (wdx
= 0 ; wdx
< vector_width
; wdx
+= 1)
1466 fprintf(vvp_out
, "%c", identity_val
);
1467 fprintf(vvp_out
, ">");
1470 fprintf(vvp_out
, ";\n");
1473 ninp
= (ninp
+3) / 4;
1479 /* Free the array of char*. The strings themselves are
1480 persistent, held by the ivl_nexus_t objects. */
1481 free(input_strings
);
1483 /* If there are delays, then draw the delay functor to carry
1484 that delay. This is the final output. */
1485 if (need_delay_flag
) {
1486 ivl_expr_t rise_exp
= ivl_logic_delay(lptr
,0);
1487 ivl_expr_t fall_exp
= ivl_logic_delay(lptr
,1);
1488 ivl_expr_t decay_exp
= ivl_logic_delay(lptr
,2);
1490 if (number_is_immediate(rise_exp
,64)
1491 && number_is_immediate(fall_exp
,64)
1492 && number_is_immediate(decay_exp
,64)) {
1494 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1495 lptr
, get_number_immediate(rise_exp
),
1496 get_number_immediate(rise_exp
),
1497 get_number_immediate(rise_exp
), lptr
);
1500 assert(ivl_expr_type(rise_exp
) == IVL_EX_SIGNAL
);
1501 assert(ivl_expr_type(fall_exp
) == IVL_EX_SIGNAL
);
1502 assert(ivl_expr_type(decay_exp
) == IVL_EX_SIGNAL
);
1504 fprintf(vvp_out
, "L_%p .delay L_%p/d", lptr
, lptr
);
1506 sig
= ivl_expr_signal(rise_exp
);
1507 assert(ivl_signal_array_count(sig
) == 1);
1508 fprintf(vvp_out
, ", v%p_0", sig
);
1510 sig
= ivl_expr_signal(fall_exp
);
1511 assert(ivl_signal_array_count(sig
) == 1);
1512 fprintf(vvp_out
, ", v%p_0", sig
);
1514 sig
= ivl_expr_signal(decay_exp
);
1515 assert(ivl_signal_array_count(sig
) == 1);
1516 fprintf(vvp_out
, ", v%p_0;\n", sig
);
1521 static void draw_event_in_scope(ivl_event_t obj
)
1523 unsigned nany
= ivl_event_nany(obj
);
1524 unsigned nneg
= ivl_event_nneg(obj
);
1525 unsigned npos
= ivl_event_npos(obj
);
1529 /* Figure out how many probe functors are needed. */
1531 cnt
+= (nany
+3) / 4;
1534 cnt
+= (nneg
+3) / 4;
1537 cnt
+= (npos
+3) / 4;
1540 /* If none are needed, then this is a named event. The
1541 code needed is easy. */
1542 fprintf(vvp_out
, "E_%p .event \"%s\";\n", obj
,
1543 vvp_mangle_name(ivl_event_basename(obj
)));
1545 } else if (cnt
> 1) {
1546 /* There are a bunch of events that need to be event/or
1551 for (idx
= 0 ; idx
< nany
; idx
+= 4, ecnt
+= 1) {
1554 fprintf(vvp_out
, "E_%p/%u .event edge", obj
, ecnt
);
1559 for (sub
= idx
; sub
< top
; sub
+= 1) {
1560 ivl_nexus_t nex
= ivl_event_any(obj
, sub
);
1561 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1563 fprintf(vvp_out
, ";\n");
1566 for (idx
= 0 ; idx
< nneg
; idx
+= 4, ecnt
+= 1) {
1569 fprintf(vvp_out
, "E_%p/%u .event negedge", obj
, ecnt
);
1574 for (sub
= idx
; sub
< top
; sub
+= 1) {
1575 ivl_nexus_t nex
= ivl_event_neg(obj
, sub
);
1576 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1578 fprintf(vvp_out
, ";\n");
1581 for (idx
= 0 ; idx
< npos
; idx
+= 4, ecnt
+= 1) {
1584 fprintf(vvp_out
, "E_%p/%u .event posedge", obj
, ecnt
);
1589 for (sub
= idx
; sub
< top
; sub
+= 1) {
1590 ivl_nexus_t nex
= ivl_event_pos(obj
, sub
);
1591 fprintf(vvp_out
, ", %s", draw_input_from_net(nex
));
1593 fprintf(vvp_out
, ";\n");
1596 assert(ecnt
== cnt
);
1598 fprintf(vvp_out
, "E_%p .event/or", obj
);
1599 fprintf(vvp_out
, " E_%p/0", obj
);
1601 for (idx
= 1 ; idx
< cnt
; idx
+= 1)
1602 fprintf(vvp_out
, ", E_%p/%u", obj
, idx
);
1604 fprintf(vvp_out
, ";\n");
1607 unsigned num_input_strings
= nany
+ nneg
+ npos
;
1609 ivl_nexus_t input_nexa
[4];
1610 const char*edge
= 0;
1612 assert(num_input_strings
<= 4);
1615 assert((nneg
+ npos
) == 0);
1620 for (idx
= 0 ; idx
< nany
; idx
+= 1) {
1621 ivl_nexus_t nex
= ivl_event_any(obj
, idx
);
1622 input_nexa
[idx
] = nex
;
1625 } else if (nneg
> 0) {
1626 assert((nany
+ npos
) == 0);
1629 for (idx
= 0 ; idx
< nneg
; idx
+= 1) {
1630 ivl_nexus_t nex
= ivl_event_neg(obj
, idx
);
1631 input_nexa
[idx
] = nex
;
1635 assert((nany
+ nneg
) == 0);
1638 for (idx
= 0 ; idx
< npos
; idx
+= 1) {
1639 ivl_nexus_t nex
= ivl_event_pos(obj
, idx
);
1640 input_nexa
[idx
] = nex
;
1644 fprintf(vvp_out
, "E_%p .event %s", obj
, edge
);
1645 for (idx
= 0 ; idx
< num_input_strings
; idx
+= 1)
1646 fprintf(vvp_out
, ", %s", draw_input_from_net(input_nexa
[idx
]));
1648 fprintf(vvp_out
, ";\n");
1653 * This function draws any functors needed to calculate the input to
1654 * this nexus, and leaves in the data array strings that can be used
1655 * as functor arguments. The strings are from the draw_net_input
1656 * function, which in turn returns nexus names, so the strings are
1657 * safe to pass around.
1659 static void draw_lpm_data_inputs(ivl_lpm_t net
, unsigned base
,
1660 unsigned ndata
, const char**src_table
)
1663 for (idx
= 0 ; idx
< ndata
; idx
+= 1) {
1664 ivl_nexus_t nex
= ivl_lpm_data(net
, base
+idx
);
1665 src_table
[idx
] = draw_net_input(nex
);
1670 * If needed, draw a .delay node to delay the output from the LPM
1671 * device. Return the "/d" string if we drew this .delay node, or the
1672 * "" string if the node was not needed. The caller uses that string
1673 * to modify labels that are generated.
1675 static const char* draw_lpm_output_delay(ivl_lpm_t net
)
1677 ivl_expr_t d_rise
= ivl_lpm_delay(net
, 0);
1678 ivl_expr_t d_fall
= ivl_lpm_delay(net
, 1);
1679 ivl_expr_t d_decay
= ivl_lpm_delay(net
, 2);
1681 const char*dly
= "";
1683 assert(number_is_immediate(d_rise
, 64));
1684 assert(number_is_immediate(d_fall
, 64));
1685 assert(number_is_immediate(d_decay
, 64));
1687 fprintf(vvp_out
, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n",
1688 net
, get_number_immediate(d_rise
),
1689 get_number_immediate(d_rise
),
1690 get_number_immediate(d_rise
), net
);
1696 static void draw_lpm_add(ivl_lpm_t net
)
1698 const char*src_table
[2];
1700 const char*type
= "";
1701 ivl_variable_type_t dta
= data_type_of_nexus(ivl_lpm_data(net
,0));
1702 ivl_variable_type_t dtb
= data_type_of_nexus(ivl_lpm_data(net
,1));
1703 ivl_variable_type_t dto
= IVL_VT_LOGIC
;
1705 if (dta
== IVL_VT_REAL
|| dtb
== IVL_VT_REAL
)
1708 width
= ivl_lpm_width(net
);
1710 switch (ivl_lpm_type(net
)) {
1712 if (dto
== IVL_VT_REAL
)
1718 if (dto
== IVL_VT_REAL
)
1724 if (dto
== IVL_VT_REAL
)
1729 case IVL_LPM_DIVIDE
:
1730 if (dto
== IVL_VT_REAL
)
1732 else if (ivl_lpm_signed(net
))
1738 if (dto
== IVL_VT_REAL
)
1744 if (dto
== IVL_VT_REAL
)
1746 else if (ivl_lpm_signed(net
)) {
1748 if (width
> 8*sizeof(long)) {
1749 fprintf(stderr
, "%s:%u: sorry (vvp-tgt): Signed power "
1750 "result must be no more than %zu bits.\n",
1751 ivl_lpm_file(net
), ivl_lpm_lineno(net
),
1762 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1764 const char*dly
= draw_lpm_output_delay(net
);
1766 fprintf(vvp_out
, "L_%p%s .arith/%s %u, %s, %s;\n",
1767 net
, dly
, type
, width
, src_table
[0], src_table
[1]);
1771 * The read port to an array is generated as a single record that takes
1772 * the address as an input.
1774 static void draw_lpm_array(ivl_lpm_t net
)
1777 ivl_signal_t mem
= ivl_lpm_array(net
);
1779 fprintf(vvp_out
, "L_%p .array/port v%p, ", net
, mem
);
1781 nex
= ivl_lpm_select(net
);
1782 fprintf(vvp_out
, "%s", draw_net_input(nex
));
1784 fprintf(vvp_out
, ";\n");
1787 static void draw_lpm_cmp(ivl_lpm_t net
)
1789 const char*src_table
[2];
1791 const char*type
= "";
1792 const char*signed_string
= ivl_lpm_signed(net
)? ".s" : "";
1793 ivl_variable_type_t dta
= data_type_of_nexus(ivl_lpm_data(net
,0));
1794 ivl_variable_type_t dtb
= data_type_of_nexus(ivl_lpm_data(net
,1));
1795 ivl_variable_type_t dtc
= IVL_VT_LOGIC
;
1797 if (dta
== IVL_VT_REAL
|| dtb
== IVL_VT_REAL
)
1800 width
= ivl_lpm_width(net
);
1802 switch (ivl_lpm_type(net
)) {
1803 case IVL_LPM_CMP_EEQ
:
1804 assert(dtc
!= IVL_VT_REAL
); /* Should never get here! */
1808 case IVL_LPM_CMP_EQ
:
1809 if (dtc
== IVL_VT_REAL
)
1815 case IVL_LPM_CMP_GE
:
1816 if (dtc
== IVL_VT_REAL
) {
1822 case IVL_LPM_CMP_GT
:
1823 if (dtc
== IVL_VT_REAL
) {
1829 case IVL_LPM_CMP_NE
:
1830 if (dtc
== IVL_VT_REAL
)
1836 case IVL_LPM_CMP_NEE
:
1837 assert(dtc
!= IVL_VT_REAL
); /* Should never get here! */
1845 draw_lpm_data_inputs(net
, 0, 2, src_table
);
1847 const char*dly
= draw_lpm_output_delay(net
);
1849 fprintf(vvp_out
, "L_%p%s .cmp/%s%s %u, %s, %s;\n",
1850 net
, dly
, type
, signed_string
, width
,
1851 src_table
[0], src_table
[1]);
1855 * This function draws the arguments to a .const node using the
1856 * lpm inputs starting at "start" and for "cnt" inputs. This input
1857 * count must be <= 4. It is up to the caller to write the header part
1858 * of the statement, and to organize the data into multiple
1861 * Return the width of the final concatenation.
1863 static unsigned lpm_concat_inputs(ivl_lpm_t net
, unsigned start
,
1864 unsigned cnt
, const char*src_table
[])
1871 /* First, draw the [L M N O] part of the statement, the list
1872 of widths for the .concat statement. */
1873 fprintf(vvp_out
, "[");
1875 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1876 ivl_nexus_t nex
= ivl_lpm_data(net
, start
+idx
);
1877 unsigned nexus_width
= width_of_nexus(nex
);
1878 fprintf(vvp_out
, " %u", nexus_width
);
1882 for ( ; idx
< 4 ; idx
+= 1)
1883 fprintf(vvp_out
, " 0");
1885 fprintf(vvp_out
, "]");
1888 for (idx
= 0 ; idx
< cnt
; idx
+= 1) {
1889 fprintf(vvp_out
, ", %s", src_table
[idx
]);
1892 fprintf(vvp_out
, ";\n");
1897 * Implement the general IVL_LPM_CONCAT using .concat nodes. Use as
1898 * many nested nodes as necessary to support the desired number of
1901 static void draw_lpm_concat(ivl_lpm_t net
)
1903 const char*src_table
[4];
1904 unsigned icnt
= ivl_lpm_selects(net
);
1905 const char*dly
= draw_lpm_output_delay(net
);
1908 /* This is the easiest case. There are 4 or fewer input
1909 vectors, so the entire IVL_LPM_CONCAT can be
1910 implemented with a single .concat node. */
1911 draw_lpm_data_inputs(net
, 0, icnt
, src_table
);
1912 fprintf(vvp_out
, "L_%p%s .concat ", net
, dly
);
1913 lpm_concat_inputs(net
, 0, icnt
, src_table
);
1916 /* If there are more than 4 inputs, things get more
1917 complicated. We need to generate a balanced tree of
1918 .concat nodes to blend the inputs down to a single
1919 root node, that becomes the output from the
1921 unsigned idx
, depth
;
1922 struct concat_tree
{
1927 tree
= malloc((icnt
+ 3)/4 * sizeof(struct concat_tree
));
1929 /* First, fill in all the leaves with the initial inputs
1930 to the tree. After this loop, there are (icnt+3)/4
1931 .concat nodes drawn, that together take all the
1933 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1936 if ((idx
+ trans
) > icnt
)
1939 draw_lpm_data_inputs(net
, idx
, trans
, src_table
);
1940 fprintf(vvp_out
, "LS_%p_0_%u .concat ", net
, idx
);
1941 wid
= lpm_concat_inputs(net
, idx
, trans
, src_table
);
1943 tree
[idx
/4].base
= idx
;
1944 tree
[idx
/4].wid
= wid
;
1947 /* icnt is the input count for the level. It is the
1948 number of .concats of the previous level that have to
1949 be concatenated at the current level. (This is not
1950 the same as the bit width.) */
1951 icnt
= (icnt
+ 3)/4;
1953 /* Tree now has icnt nodes that are depth=0 concat nodes
1954 which take in the leaf inputs. The while loop below
1955 starts and ends with a tree of icnt nodes. Each time
1956 through, there are 1/4 the nodes we started
1957 with. Thus, we eventually get down to <=4 nodes, and
1958 that is when we fall out of the loop. */
1962 for (idx
= 0 ; idx
< icnt
; idx
+= 4) {
1966 if ((idx
+trans
) > icnt
)
1969 fprintf(vvp_out
, "LS_%p_%u_%u .concat [",
1972 for (tdx
= 0 ; tdx
< trans
; tdx
+= 1) {
1973 fprintf(vvp_out
, " %u", tree
[idx
+tdx
].wid
);
1974 wid
+= tree
[idx
+tdx
].wid
;
1977 for ( ; tdx
< 4 ; tdx
+= 1)
1978 fprintf(vvp_out
, " 0");
1980 fprintf(vvp_out
, "]");
1982 for (tdx
= 0; tdx
< trans
; tdx
+= 1) {
1983 fprintf(vvp_out
, ", LS_%p_%u_%u", net
,
1984 depth
-1, tree
[idx
+tdx
].base
);
1987 fprintf(vvp_out
, ";\n");
1988 tree
[idx
/4].base
= idx
;
1989 tree
[idx
/4].wid
= wid
;
1993 icnt
= (icnt
+ 3)/4;
1996 /* Finally, draw the root node that takes in the final
1997 row of tree nodes and generates a single output. */
1998 fprintf(vvp_out
, "L_%p%s .concat [", net
, dly
);
1999 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
2000 fprintf(vvp_out
, " %u", tree
[idx
].wid
);
2001 for ( ; idx
< 4 ; idx
+= 1)
2002 fprintf(vvp_out
, " 0");
2003 fprintf(vvp_out
, "]");
2005 for (idx
= 0 ; idx
< icnt
; idx
+= 1)
2006 fprintf(vvp_out
, ", LS_%p_%u_%u",
2007 net
, depth
-1, tree
[idx
].base
);
2009 fprintf(vvp_out
, ";\n");
2015 * primitive FD (q, clk, ce, d);
2020 * // clk ce d r s q q+
2021 * r 1 0 0 0 : ? : 0;
2022 * r 1 1 0 0 : ? : 1;
2023 * f 1 ? 0 0 : ? : -;
2024 * ? 1 ? 0 0 : ? : -;
2025 * * 0 ? 0 0 : ? : -;
2026 * ? ? ? 1 ? : ? : 0;
2027 * ? ? ? 0 1 : ? : 1;
2031 static void draw_lpm_ff(ivl_lpm_t net
)
2033 ivl_expr_t aset_expr
= 0;
2034 const char*aset_bits
= 0;
2039 width
= ivl_lpm_width(net
);
2041 aset_expr
= ivl_lpm_aset_value(net
);
2043 assert(ivl_expr_width(aset_expr
) == width
);
2044 aset_bits
= ivl_expr_bits(aset_expr
);
2048 fprintf(vvp_out
, "L_%p .dff ", net
);
2050 nex
= ivl_lpm_data(net
,0);
2052 fprintf(vvp_out
, "%s", draw_net_input(nex
));
2054 nex
= ivl_lpm_clk(net
);
2056 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
2058 nex
= ivl_lpm_enable(net
);
2060 fprintf(vvp_out
, ", %s", draw_net_input(nex
));
2062 fprintf(vvp_out
, ", C4<1>");
2065 /* Stub asynchronous input for now. */
2066 fprintf(vvp_out
, ", C4<z>");
2068 fprintf(vvp_out
, ";\n");
2071 static void draw_lpm_shiftl(ivl_lpm_t net
)
2073 unsigned width
= ivl_lpm_width(net
);
2074 const char* signed_flag
= ivl_lpm_signed(net
)? "s" : "";
2075 const char*dly
= draw_lpm_output_delay(net
);
2077 if (ivl_lpm_type(net
) == IVL_LPM_SHIFTR
)
2078 fprintf(vvp_out
, "L_%p%s .shift/r%s %u", net
, dly
, signed_flag
,
2081 fprintf(vvp_out
, "L_%p%s .shift/l %u", net
, dly
, width
);
2083 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 0)));
2085 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, 1)));
2087 fprintf(vvp_out
, ";\n");
2090 static void draw_type_string_of_nex(ivl_nexus_t nex
)
2092 switch (data_type_of_nexus(nex
)) {
2094 fprintf(vvp_out
, "r");
2098 fprintf(vvp_out
, "v%d", width_of_nexus(nex
));
2106 static void draw_lpm_sfunc(ivl_lpm_t net
)
2110 const char*dly
= draw_lpm_output_delay(net
);
2112 fprintf(vvp_out
, "L_%p%s .sfunc %u %u \"%s\"", net
, dly
,
2113 ivl_file_table_index(ivl_lpm_file(net
)), ivl_lpm_lineno(net
),
2114 ivl_lpm_string(net
));
2116 /* Print the function type descriptor string. */
2117 fprintf(vvp_out
, ", \"");
2119 draw_type_string_of_nex(ivl_lpm_q(net
,0));
2121 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1)
2122 draw_type_string_of_nex(ivl_lpm_data(net
,idx
));
2124 fprintf(vvp_out
, "\"");
2126 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2127 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
,idx
)));
2130 fprintf(vvp_out
, ";\n");
2133 static void draw_lpm_ufunc(ivl_lpm_t net
)
2136 ivl_scope_t def
= ivl_lpm_define(net
);
2138 const char*dly
= draw_lpm_output_delay(net
);
2140 fprintf(vvp_out
, "L_%p%s .ufunc TD_%s, %u", net
, dly
,
2141 vvp_mangle_id(ivl_scope_name(def
)),
2142 ivl_lpm_width(net
));
2144 /* Print all the net signals that connect to the input of the
2146 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2147 fprintf(vvp_out
, ", %s", draw_net_input(ivl_lpm_data(net
, idx
)));
2151 assert((ivl_lpm_size(net
)+1) == ivl_scope_ports(def
));
2153 /* Now print all the variables in the function scope that
2154 receive the input values given in the previous list. */
2155 for (idx
= 0 ; idx
< ivl_lpm_size(net
) ; idx
+= 1) {
2156 ivl_signal_t psig
= ivl_scope_port(def
, idx
+1);
2159 fprintf(vvp_out
, " (");
2161 fprintf(vvp_out
, ", ");
2163 assert(ivl_signal_array_count(psig
) == 1);
2164 fprintf(vvp_out
, "v%p_0", psig
);
2167 fprintf(vvp_out
, ")");
2169 /* Finally, print the reference to the signal from which the
2170 result is collected. */
2171 { ivl_signal_t psig
= ivl_scope_port(def
, 0);
2172 assert(ivl_lpm_width(net
) == ivl_signal_width(psig
));
2173 assert(ivl_signal_array_count(psig
) == 1);
2175 fprintf(vvp_out
, " v%p_0", psig
);
2178 fprintf(vvp_out
, ";\n");
2182 * Handle a PART SELECT device. This has a single input and output,
2183 * plus an optional extra input that is a non-constant base.
2185 static void draw_lpm_part(ivl_lpm_t net
)
2187 unsigned width
, base
;
2190 const char*dly
= draw_lpm_output_delay(net
);
2192 width
= ivl_lpm_width(net
);
2193 base
= ivl_lpm_base(net
);
2194 sel
= ivl_lpm_data(net
,1);
2197 fprintf(vvp_out
, "L_%p%s .part %s",
2198 net
, dly
, draw_net_input(ivl_lpm_data(net
, 0)));
2199 fprintf(vvp_out
, ", %u, %u;\n", base
, width
);
2201 fprintf(vvp_out
, "L_%p%s .part/v %s",
2202 net
, dly
, draw_net_input(ivl_lpm_data(net
,0)));
2203 fprintf(vvp_out
, ", %s", draw_net_input(sel
));
2204 fprintf(vvp_out
, ", %u;\n", width
);
2209 * Handle a PART SELECT PV device. Generate a .part/pv node that
2210 * includes the part input, and the geometry of the part.
2212 static void draw_lpm_part_pv(ivl_lpm_t net
)
2214 unsigned width
= ivl_lpm_width(net
);
2215 unsigned base
= ivl_lpm_base(net
);
2216 unsigned signal_width
= width_of_nexus(ivl_lpm_q(net
,0));
2218 fprintf(vvp_out
, "L_%p .part/pv %s",
2219 net
, draw_net_input(ivl_lpm_data(net
, 0)));
2221 fprintf(vvp_out
, ", %u, %u, %u;\n", base
, width
, signal_width
);
2225 * Handle the drawing of a bi-directional part select. The two ports
2226 * are simultaneously input and output. A simple minded connect of the
2227 * input to the output causes a functor cycle which will lock into an
2228 * X value, so something special is needed.
2230 * NOTE: The inputs of the tran device at this point need to be from
2231 * all the drivers of the nexus *except* the tran itself. This
2232 * function will draw three labels that can be linked:
2234 * The ivl_lpm_q of a part(bi) may be a smaller vector then the
2235 * ivl_lpm_data, the tran acts like a forward part select in that
2238 * The device creates these nodes:
2241 * This is the Q port of the tran resolved and padded to the maximum
2242 * width of the tran. The tran itself is not included in the
2243 * resolution of this port.
2246 * This is the Q and D parts resolved together, still without the tran
2250 * This is the /V node part-selected back to the dimensions of the Q
2253 static void draw_lpm_part_bi(ivl_lpm_t net
)
2255 unsigned width
= ivl_lpm_width(net
);
2256 unsigned base
= ivl_lpm_base(net
);
2257 unsigned signal_width
= width_of_nexus(ivl_lpm_data(net
,0));
2261 ivl_nexus_ptr_t ptr
= 0;
2266 /* It seems implausible that the two inputs of a tran will be
2267 connected together. So assert that this is so to simplify
2268 the code to look for the nexus_ptr_t objects. */
2269 assert(ivl_lpm_q(net
,0) != ivl_lpm_data(net
,0));
2271 nex
= ivl_lpm_q(net
,0);
2272 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2273 ptr
= ivl_nexus_ptr(nex
, idx
);
2274 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2278 p_str
= draw_net_input_x(nex
, ptr
, 0, 0);
2280 nex
= ivl_lpm_data(net
,0);
2281 for (idx
= 0 ; idx
< ivl_nexus_ptrs(nex
) ; idx
+= 1) {
2282 ptr
= ivl_nexus_ptr(nex
, idx
);
2283 if (ivl_nexus_ptr_lpm(ptr
) == net
)
2286 v_str
= draw_net_input_x(nex
, ptr
, OMIT_PART_BI_DATA
, 0);
2288 /* Pad the part-sized input out to a common width...
2289 The /i label is the Q side of the tran, resolved except for
2290 the tran itself and padded (with z) to the larger width. */
2291 fprintf(vvp_out
, "L_%p/i .part/pv %s, %u, %u, %u;\n",
2292 net
, p_str
, base
, width
, signal_width
);
2294 /* Resolve together the two halves of the tran...
2295 The /V label is the ports of the tran (now the same width)
2296 resolved together. Neither input to this resolver includes
2298 fprintf(vvp_out
, "L_%p/V .resolv tri, L_%p/i, %s;\n",
2301 /* The full-width side is created by the tran device, all we
2302 have left to to is take a part select of that for the
2303 smaller output, and this becomes the part select output of
2305 fprintf(vvp_out
, "L_%p/P .part L_%p/V, %u, %u;\n", net
,
2313 * Draw unary reduction devices.
2315 static void draw_lpm_re(ivl_lpm_t net
, const char*type
)
2317 const char*dly
= draw_lpm_output_delay(net
);
2319 fprintf(vvp_out
, "L_%p%s .reduce/%s %s;\n", net
, dly
,
2320 type
, draw_net_input(ivl_lpm_data(net
,0)));
2323 static void draw_lpm_repeat(ivl_lpm_t net
)
2325 fprintf(vvp_out
, "L_%p .repeat %u, %u, %s;\n", net
,
2326 ivl_lpm_width(net
), ivl_lpm_size(net
),
2327 draw_net_input(ivl_lpm_data(net
,0)));
2330 static void draw_lpm_sign_ext(ivl_lpm_t net
)
2332 fprintf(vvp_out
, "L_%p .extend/s %u, %s;\n",
2333 net
, ivl_lpm_width(net
),
2334 draw_net_input(ivl_lpm_data(net
,0)));
2337 static void draw_lpm_in_scope(ivl_lpm_t net
)
2339 switch (ivl_lpm_type(net
)) {
2344 case IVL_LPM_DIVIDE
:
2351 draw_lpm_array(net
);
2354 case IVL_LPM_PART_BI
:
2355 draw_lpm_part_bi(net
);
2358 case IVL_LPM_PART_VP
:
2362 case IVL_LPM_PART_PV
:
2363 draw_lpm_part_pv(net
);
2366 case IVL_LPM_CONCAT
:
2367 draw_lpm_concat(net
);
2374 case IVL_LPM_CMP_EEQ
:
2375 case IVL_LPM_CMP_EQ
:
2376 case IVL_LPM_CMP_GE
:
2377 case IVL_LPM_CMP_GT
:
2378 case IVL_LPM_CMP_NE
:
2379 case IVL_LPM_CMP_NEE
:
2387 case IVL_LPM_RE_AND
:
2388 draw_lpm_re(net
, "and");
2391 draw_lpm_re(net
, "or");
2393 case IVL_LPM_RE_XOR
:
2394 draw_lpm_re(net
, "xor");
2396 case IVL_LPM_RE_NAND
:
2397 draw_lpm_re(net
, "nand");
2399 case IVL_LPM_RE_NOR
:
2400 draw_lpm_re(net
, "nor");
2402 case IVL_LPM_RE_XNOR
:
2403 draw_lpm_re(net
, "xnor");
2406 case IVL_LPM_REPEAT
:
2407 draw_lpm_repeat(net
);
2410 case IVL_LPM_SHIFTL
:
2411 case IVL_LPM_SHIFTR
:
2412 draw_lpm_shiftl(net
);
2415 case IVL_LPM_SIGN_EXT
:
2416 draw_lpm_sign_ext(net
);
2420 draw_lpm_sfunc(net
);
2424 draw_lpm_ufunc(net
);
2428 fprintf(stderr
, "XXXX LPM not supported: %s.%s\n",
2429 ivl_scope_name(ivl_lpm_scope(net
)), ivl_lpm_basename(net
));
2433 int draw_scope(ivl_scope_t net
, ivl_scope_t parent
)
2437 switch (ivl_scope_type(net
)) {
2438 case IVL_SCT_MODULE
: type
= "module"; break;
2439 case IVL_SCT_FUNCTION
: type
= "function"; break;
2440 case IVL_SCT_TASK
: type
= "task"; break;
2441 case IVL_SCT_BEGIN
: type
= "begin"; break;
2442 case IVL_SCT_FORK
: type
= "fork"; break;
2443 case IVL_SCT_GENERATE
: type
= "generate"; break;
2444 default: type
= "?"; assert(0);
2447 fprintf(vvp_out
, "S_%p .scope %s, \"%s\" \"%s\" %d %d",
2448 net
, type
, vvp_mangle_name(ivl_scope_basename(net
)),
2449 ivl_scope_tname(net
), ivl_file_table_index(ivl_scope_file(net
)),
2450 ivl_scope_lineno(net
));
2453 fprintf(vvp_out
, ", %d %d, S_%p;\n",
2454 ivl_file_table_index(ivl_scope_def_file(net
)),
2455 ivl_scope_def_lineno(net
), parent
);
2458 fprintf(vvp_out
, ";\n");
2461 fprintf(vvp_out
, " .timescale %d %d;\n", ivl_scope_time_units(net
),
2462 ivl_scope_time_precision(net
));
2464 for (idx
= 0 ; idx
< ivl_scope_params(net
) ; idx
+= 1) {
2465 ivl_parameter_t par
= ivl_scope_param(net
, idx
);
2466 ivl_expr_t pex
= ivl_parameter_expr(par
);
2467 switch (ivl_expr_type(pex
)) {
2469 fprintf(vvp_out
, "P_%p .param/str \"%s\" %d %d, \"%s\";\n",
2470 par
, ivl_parameter_basename(par
),
2471 ivl_file_table_index(ivl_parameter_file(par
)),
2472 ivl_parameter_lineno(par
),
2473 ivl_expr_string(pex
));
2476 fprintf(vvp_out
, "P_%p .param/l \"%s\" %d %d, %sC4<",
2477 par
, ivl_parameter_basename(par
),
2478 ivl_file_table_index(ivl_parameter_file(par
)),
2479 ivl_parameter_lineno(par
),
2480 ivl_expr_signed(pex
)? "+":"");
2481 { const char*bits
= ivl_expr_bits(pex
);
2482 unsigned nbits
= ivl_expr_width(pex
);
2484 for (bb
= 0 ; bb
< nbits
; bb
+= 1)
2485 fprintf(vvp_out
, "%c", bits
[nbits
-bb
-1]);
2487 fprintf(vvp_out
, ">;\n");
2489 case IVL_EX_REALNUM
:
2490 fprintf(vvp_out
, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n",
2491 par
, ivl_parameter_basename(par
),
2492 ivl_file_table_index(ivl_parameter_file(par
)),
2493 ivl_parameter_lineno(par
),
2494 draw_Cr_to_string(ivl_expr_dvalue(pex
)),
2495 ivl_expr_dvalue(pex
));
2498 fprintf(vvp_out
, "; parameter type %d unsupported\n",
2499 ivl_expr_type(pex
));
2504 /* Scan the scope for logic devices. For each device, draw out
2505 a functor that connects pin 0 to the output, and the
2506 remaining pins to inputs. */
2508 for (idx
= 0 ; idx
< ivl_scope_logs(net
) ; idx
+= 1) {
2509 ivl_net_logic_t lptr
= ivl_scope_log(net
, idx
);
2510 draw_logic_in_scope(lptr
);
2514 /* Scan the signals (reg and net) and draw the appropriate
2515 statements to make the signal function. */
2517 for (idx
= 0 ; idx
< ivl_scope_sigs(net
) ; idx
+= 1) {
2518 ivl_signal_t sig
= ivl_scope_sig(net
, idx
);
2520 switch (ivl_signal_type(sig
)) {
2522 draw_reg_in_scope(sig
);
2525 draw_net_in_scope(sig
);
2530 for (idx
= 0 ; idx
< ivl_scope_events(net
) ; idx
+= 1) {
2531 ivl_event_t event
= ivl_scope_event(net
, idx
);
2532 draw_event_in_scope(event
);
2535 for (idx
= 0 ; idx
< ivl_scope_lpms(net
) ; idx
+= 1) {
2536 ivl_lpm_t lpm
= ivl_scope_lpm(net
, idx
);
2537 draw_lpm_in_scope(lpm
);
2540 if (ivl_scope_type(net
) == IVL_SCT_TASK
)
2541 draw_task_definition(net
);
2543 if (ivl_scope_type(net
) == IVL_SCT_FUNCTION
)
2544 draw_func_definition(net
);
2546 ivl_scope_children(net
, (ivl_scope_f
*) draw_scope
, net
);