diff --git a/tgt-stub/switches.c b/tgt-stub/switches.c index 8ac087f5d..038d2c282 100644 --- a/tgt-stub/switches.c +++ b/tgt-stub/switches.c @@ -114,7 +114,8 @@ void show_switch(ivl_switch_t net) if (has_enable) { ivl_nexus_t nexe = ivl_switch_enable(net); - fprintf(out, " E: %p\n", nexe); + ivl_variable_type_t nexe_type = type_of_nexus(nexe); + fprintf(out, " E: %p \n", nexe, data_type_string(nexe_type)); if (width_of_nexus(nexe) != 1) { fprintf(out, " E: ERROR: Nexus width is %u\n", width_of_nexus(nexe)); diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index e2054785c..17f6f6240 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -499,8 +499,9 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) return strdup("C"); } -static char* draw_island_port(ivl_island_t island, - ivl_nexus_t nex, const char*src) +static char* draw_island_port(ivl_island_t island, int island_input_flag, + ivl_nexus_t nex, struct vvp_nexus_data*nex_data, + const char*src) { char result[64]; if (ivl_island_flag_test(island,0) == 0) { @@ -508,10 +509,19 @@ static char* draw_island_port(ivl_island_t island, ivl_island_flag_set(island,0,1); } - fprintf(vvp_out, "p%p .port I%p, %s;\n", nex, island, src); snprintf(result, sizeof result, "p%p", nex); + assert(nex_data->island == 0); + nex_data->island = island; + assert(nex_data->island_input == 0); + nex_data->island_input = strdup(result); - return strdup(result); + if (island_input_flag) { + fprintf(vvp_out, "p%p .import I%p, %s;\n", nex, island, src); + return strdup(src); + } else { + fprintf(vvp_out, "p%p .port I%p, %s;\n", nex, island, src); + return strdup(nex_data->island_input); + } } /* @@ -526,8 +536,6 @@ static char* draw_island_port(ivl_island_t island, * does *not* check for a previously calculated string. Use the * draw_net_input for the general case. */ - /* Omit LPMPART_BI device pin-data(0) drivers. */ -# define OMIT_PART_BI_DATA 0x0001 static ivl_nexus_ptr_t *drivers = 0x0; static unsigned adrivers = 0; @@ -539,11 +547,11 @@ void EOC_cleanup_drivers() adrivers = 0; } -char* draw_net_input_x(ivl_nexus_t nex, - ivl_nexus_ptr_t omit_ptr, int omit_flags, - struct vvp_nexus_data*nex_data) +static void draw_net_input_x(ivl_nexus_t nex, + struct vvp_nexus_data*nex_data) { ivl_island_t island = 0; + int island_input_flag = -1; ivl_signal_type_t res; char result[512]; unsigned idx; @@ -585,26 +593,26 @@ char* draw_net_input_x(ivl_nexus_t nex, for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { - ivl_lpm_t lpm_tmp; ivl_switch_t sw = 0; ivl_nexus_ptr_t nptr = ivl_nexus_ptr(nex, idx); /* If this object is part of an island, then we'll be - making a port. Save the island cookie. */ + making a port. If this nexus is an output to any + switches in the island, then set island_input_flag to + true. Save the island cookie. */ if ( (sw = ivl_nexus_ptr_switch(nptr)) ) { - island = ivl_switch_island(sw); + assert(island == 0 || island == ivl_switch_island(sw)); + island = ivl_switch_island(sw); + if (nex == ivl_switch_a(sw)) + island_input_flag = 0; + else if (nex == ivl_switch_b(sw)) + island_input_flag = 0; + else if (island_input_flag == -1) { + assert(nex == ivl_switch_enable(sw)); + island_input_flag = 1; + } } - /* If we are supposed to skip LPM_PART_BI data pins, - check that this driver is that. */ - if ((omit_flags&OMIT_PART_BI_DATA) - && (lpm_tmp = ivl_nexus_ptr_lpm(nptr)) - && (nex == ivl_lpm_data(lpm_tmp,0))) - continue; - - if (nptr == omit_ptr) - continue; - /* Skip input only pins. */ if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_HiZ) && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_HiZ)) @@ -626,12 +634,13 @@ char* draw_net_input_x(ivl_nexus_t nex, ndrivers += 1; } - /* If the caller is collecting nexus information, then save - the nexus driver count in the nex_data. */ - if (nex_data) { - nex_data->drivers_count = ndrivers; - nex_data->flags |= nex_flags; - } + if (island_input_flag < 0) + island_input_flag = 0; + + /* Save the nexus driver count in the nex_data. */ + assert(nex_data); + nex_data->drivers_count = ndrivers; + nex_data->flags |= nex_flags; /* If the nexus has no drivers, then send a constant HiZ or 0.0 into the net. */ @@ -666,11 +675,13 @@ char* draw_net_input_x(ivl_nexus_t nex, } if (island) { - char*tmp2 = draw_island_port(island, nex, nex_private); + char*tmp2 = draw_island_port(island, island_input_flag, nex, nex_data, nex_private); free(nex_private); nex_private = tmp2; } - return nex_private; + assert(nex_data->net_input == 0); + nex_data->net_input = nex_private; + return; } @@ -691,11 +702,13 @@ char* draw_net_input_x(ivl_nexus_t nex, nex_private = draw_net_input_drive(nex, drivers[0]); } if (island) { - char*tmp = draw_island_port(island, nex, nex_private); + char*tmp = draw_island_port(island, island_input_flag, nex, nex_data, nex_private); free(nex_private); nex_private = tmp; } - return nex_private; + assert(nex_data->net_input == 0); + nex_data->net_input = nex_private; + return; } level = 0; @@ -742,11 +755,12 @@ char* draw_net_input_x(ivl_nexus_t nex, snprintf(result, sizeof result, "RS_%p", nex); if (island) - nex_private = draw_island_port(island, nex, result); + nex_private = draw_island_port(island, island_input_flag, nex, nex_data, result); else nex_private = strdup(result); - return nex_private; + assert(nex_data->net_input == 0); + nex_data->net_input = nex_private; } /* @@ -770,7 +784,33 @@ const char*draw_net_input(ivl_nexus_t nex) } assert(nex_data->net_input == 0); - nex_data->net_input = draw_net_input_x(nex, 0, 0, nex_data); + draw_net_input_x(nex, nex_data); return nex_data->net_input; } + +const char*draw_island_net_input(ivl_island_t island, ivl_nexus_t nex) +{ + struct vvp_nexus_data*nex_data = (struct vvp_nexus_data*) + ivl_nexus_get_private(nex); + + /* If this nexus already has a label, then its input is + already figured out. Just return the existing label. */ + if (nex_data && nex_data->island_input) { + assert(nex_data->island == island); + return nex_data->island_input; + } + + if (nex_data == 0) { + nex_data = new_nexus_data(); + ivl_nexus_set_private(nex, nex_data); + } + + assert(nex_data->net_input == 0); + draw_net_input_x(nex, nex_data); + + assert(nex_data->island == island); + assert(nex_data->island_input); + + return nex_data->island_input; +} diff --git a/tgt-vvp/draw_switch.c b/tgt-vvp/draw_switch.c index 235106cbc..622cf1b22 100644 --- a/tgt-vvp/draw_switch.c +++ b/tgt-vvp/draw_switch.c @@ -43,16 +43,16 @@ void draw_switch_in_scope(ivl_switch_t sw) nex_a = ivl_switch_a(sw); assert(nex_a); - str_a = draw_net_input(nex_a); + str_a = draw_island_net_input(island, nex_a); nex_b = ivl_switch_b(sw); assert(nex_b); - str_b = draw_net_input(nex_b); + str_b = draw_island_net_input(island, nex_b); enable = ivl_switch_enable(sw); str_e = 0; if (enable) - str_e = draw_net_input(enable); + str_e = draw_island_net_input(island, enable); switch (ivl_switch_type(sw)) { diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index f67e94506..902e5432c 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -123,6 +123,10 @@ extern void draw_switch_in_scope(ivl_switch_t sw); struct vvp_nexus_data { /* draw_net_input uses this */ const char*net_input; + /* draw_isnald_net_input uses these */ + const char*island_input; + ivl_island_t island; + /* */ unsigned drivers_count; int flags; /* draw_net_in_scope uses these to identify the controlling word. */ @@ -144,15 +148,12 @@ extern const char* draw_net_input(ivl_nexus_t nex); void EOC_cleanup_drivers(); /* - * See draw_net_input.c for details on draw_net_input_x. (It would be - * nice if this can be made private.) + * This is different from draw_net_input in that it is intended to be + * used within the network of an island. This finds and prepares the + * link for a nexus within the scope of the given island, instead of + * the net as a whole. */ - /* Omit LPMPART_BI device pin-data(0) drivers. */ -# define OMIT_PART_BI_DATA 0x0001 -struct vvp_nexus_data; -extern char* draw_net_input_x(ivl_nexus_t nex, - ivl_nexus_ptr_t omit_ptr, int omit_flags, - struct vvp_nexus_data*nex_data); +extern const char* draw_island_net_input(ivl_island_t island, ivl_nexus_t nex); /* * This function is different from draw_net_input in that it will diff --git a/vvp/vvp_island.cc b/vvp/vvp_island.cc index 9620199ee..17573cde4 100644 --- a/vvp/vvp_island.cc +++ b/vvp/vvp_island.cc @@ -271,6 +271,20 @@ vvp_island* compile_find_island(const char*island) return use_island; } +/* + * This handles the compile of a .port record. A .port is a 2-way port + * between the island and the outside. For example, + * + *