ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig == 0) continue; if (ivl_signal_local(sig)) continue; *word = ivl_nexus_ptr_pin(ptr); return sig; } return 0; }
/* * Given a nexus, look for a signal that has module delay * paths. Return that signal. (There should be no more than 1.) If we * don't find any, then return nil. */ static ivl_signal_t find_modpath(ivl_nexus_t nex) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig == 0) continue; if (ivl_signal_npath(sig) == 0) continue; return sig; } return 0; }
/* * An assignment is one of a possible list of l-values to a behavioral * assignment. Each l-value is either a part select of a signal or a * non-constant bit select. */ static void show_assign_lval(ivl_lval_t lval) { ivl_nexus_t nex; ivl_signal_t sig=NULL; unsigned idx; unsigned lsb=0; assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_mem(lval) == 0); nex = ivl_lval_pin(lval, 0); for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { unsigned pin; ivl_nexus_ptr_t ptr; ptr = ivl_nexus_ptr(nex, idx); sig = ivl_nexus_ptr_sig(ptr); if (sig == 0) continue; lsb = ivl_nexus_ptr_pin(ptr); for (pin = 1 ; pin < ivl_lval_pins(lval) ; pin += 1) { if (ivl_signal_pin(sig, lsb+pin) != ivl_lval_pin(lval,pin)) break; } if (pin < ivl_lval_pins(lval)) continue; break; } assert(sig); if ((lsb > 0) || (lsb + ivl_lval_pins(lval)) < ivl_signal_pins(sig)) { fprintf(out, "%s[%u:%u]", ivl_signal_name(sig), lsb+ivl_lval_pins(lval)-1, lsb); } else { fprintf(out, "%s", ivl_signal_name(sig)); } }
/* * This function finds the vector width of a signal. It relies on the * assumption that all the signal inputs to the nexus have the same * width. The ivl_target API should assert that condition. */ unsigned width_of_nexus(ivl_nexus_t nex) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig != 0) { return ivl_signal_width(sig); } } /* ERROR: A nexus should have at least one signal to carry properties like width. */ return 0; }
ivl_variable_type_t type_of_nexus(ivl_nexus_t net) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(net); idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(net, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig != 0) { return ivl_signal_data_type(sig); } } /* ERROR: A nexus should have at least one signal to carry properties like the data type. */ return IVL_VT_NO_TYPE; }
ivl_discipline_t discipline_of_nexus(ivl_nexus_t nex) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex); idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig != 0) { return ivl_signal_discipline(sig); } } /* ERROR: A nexus should have at least one signal to carry properties like the data type. */ return 0; }
static unsigned is_local_input(ivl_scope_t scope, ivl_nexus_t nex) { ivl_signal_t sig = 0; unsigned idx, count = ivl_nexus_ptrs(nex); for (idx = 0; idx < count; idx += 1) { ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr); if (! t_sig) continue; if (! ivl_signal_local(t_sig)) continue; if (ivl_signal_port(t_sig) != IVL_SIP_INPUT) continue; assert(! sig); assert(ivl_signal_dimensions(t_sig) == 0); sig = t_sig; } if (sig) { fprintf(vlog_out, "ivlog%s", ivl_signal_basename(sig)); return 1; } return 0; }
/* * Given a nexus, this function draws a signal reference. We don't * care really whether the signal is a reg or wire, because this may * be an input or output of a gate. Just print it. And if this is a * bit of a vector, draw the bit select needed to get at the right bit. */ static void draw_nexus(ivl_nexus_t nex) { ivl_signal_t sig=NULL; ivl_nexus_ptr_t ptr=NULL; unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ptr = ivl_nexus_ptr(nex, idx); sig = ivl_nexus_ptr_sig(ptr); if (sig) break; } assert(sig); if (ivl_signal_pins(sig) == 1) { fprintf(out, "%s", ivl_signal_name(sig)); } else { fprintf(out, "%s[%u]", ivl_signal_name(sig), ivl_nexus_ptr_pin(ptr)); } }
static ivl_signal_t find_path_source_port(ivl_delaypath_t path) { unsigned idx; ivl_nexus_t nex = ivl_path_source(path); ivl_scope_t path_scope = ivl_path_scope(path); for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(ptr); if (sig == 0) continue; if (ivl_signal_port(sig) == IVL_SIP_NONE) continue; /* The path source scope must match the modpath scope.*/ if (ivl_signal_scope(sig) != path_scope) continue; return sig; } return 0; }
static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) { unsigned nptr_pin = ivl_nexus_ptr_pin(nptr); ivl_net_const_t cptr; ivl_net_logic_t lptr; ivl_signal_t sptr; ivl_lpm_t lpm; lptr = ivl_nexus_ptr_log(nptr); if (lptr && ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT)) && (nptr_pin == 0)) do { if (! can_elide_bufz(lptr, nptr)) break; return strdup(draw_net_input(ivl_logic_pin(lptr, 1))); } while(0); /* If this is a pulldown device, then there is a single pin that drives a constant value to the entire width of the vector. The driver normally drives a pull0 value, so a C8<> constant is appropriate, but if the drive is really strong, then we can draw a C4<> constant instead. */ if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) { if (ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) { size_t result_len = ivl_logic_width(lptr) + 5; char*result = malloc(result_len); char*dp = result; strcpy(dp, "C4<"); dp += strlen(dp); str_repeat(dp, "0", ivl_logic_width(lptr)); dp += ivl_logic_width(lptr); *dp++ = '>'; *dp = 0; assert(dp >= result); assert((unsigned)(dp - result) <= result_len); return result; } else { char val[4]; size_t result_len = 3*ivl_logic_width(lptr) + 5; char*result = malloc(result_len); char*dp = result; val[0] = "01234567"[ivl_nexus_ptr_drive0(nptr)]; val[1] = val[0]; val[2] = '0'; val[3] = 0; strcpy(dp, "C8<"); dp += strlen(dp); str_repeat(dp, val, ivl_logic_width(lptr)); dp += 3*ivl_logic_width(lptr); *dp++ = '>'; *dp = 0; assert(dp >= result); assert((unsigned)(dp - result) <= result_len); return result; } } if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) { char*result; char tmp[32]; if (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG) { size_t result_len = 5 + ivl_logic_width(lptr); result = malloc(result_len); char*dp = result; strcpy(dp, "C4<"); dp += strlen(dp); str_repeat(dp, "1", ivl_logic_width(lptr)); dp += ivl_logic_width(lptr); *dp++ = '>'; *dp = 0; assert(dp >= result); assert((unsigned)(dp - result) <= result_len); } else { char val[4]; size_t result_len = 5 + 3*ivl_logic_width(lptr); result = malloc(result_len); char*dp = result; val[0] = "01234567"[ivl_nexus_ptr_drive1(nptr)]; val[1] = val[0]; val[2] = '1'; val[3] = 0; strcpy(dp, "C8<"); dp += strlen(dp); str_repeat(dp, val, ivl_logic_width(lptr)); dp += 3*ivl_logic_width(lptr); *dp++ = '>'; *dp = 0; assert(dp >= result); assert((unsigned)(dp - result) <= result_len); } /* Make the constant an argument to a BUFZ, which is what we use to drive the PULLed value. */ fprintf(vvp_out, "L_%p .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n", lptr, result); snprintf(tmp, sizeof tmp, "L_%p", lptr); result = realloc(result, strlen(tmp)+1); strcpy(result, tmp); return result; } if (lptr && (nptr_pin == 0)) { char tmp[128]; snprintf(tmp, sizeof tmp, "L_%p", lptr); return strdup(tmp); } sptr = ivl_nexus_ptr_sig(nptr); if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) { char tmp[128]; /* Input is a .var. This device may be a non-zero pin because it may be an array of reg vectors. */ snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin); if (ivl_signal_dimensions(sptr) > 0) { fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n", sptr, nptr_pin, sptr, nptr_pin); } return strdup(tmp); } cptr = ivl_nexus_ptr_con(nptr); if (cptr) { char *result = 0; ivl_expr_t d_rise, d_fall, d_decay; unsigned dly_width = 0; /* Constants should have exactly 1 pin, with a literal value. */ assert(nptr_pin == 0); switch (ivl_const_type(cptr)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: case IVL_VT_STRING: if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) { result = draw_C4_to_string(cptr); } else { result = draw_C8_to_string(cptr, ivl_nexus_ptr_drive0(nptr), ivl_nexus_ptr_drive1(nptr)); } dly_width = ivl_const_width(cptr); break; case IVL_VT_REAL: result = draw_Cr_to_string(ivl_const_real(cptr)); dly_width = 0; break; default: assert(0); break; } d_rise = ivl_const_delay(cptr, 0); d_fall = ivl_const_delay(cptr, 1); d_decay = ivl_const_delay(cptr, 2); /* We have a delayed constant, so we need to build some code. */ if (d_rise != 0) { char tmp[128]; fprintf(vvp_out, "L_%p/d .functor BUFT 1, %s, " "C4<0>, C4<0>, C4<0>;\n", cptr, result); free(result); /* Is this a fixed or variable delay? */ if (number_is_immediate(d_rise, 64, 0) && number_is_immediate(d_fall, 64, 0) && number_is_immediate(d_decay, 64, 0)) { assert(! number_is_unknown(d_rise)); assert(! number_is_unknown(d_fall)); assert(! number_is_unknown(d_decay)); fprintf(vvp_out, "L_%p .delay %u " "(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") L_%p/d;\n", cptr, dly_width, get_number_immediate64(d_rise), get_number_immediate64(d_fall), get_number_immediate64(d_decay), cptr); } else { ivl_signal_t sig; // We do not currently support calculating the decay // from the rise and fall variable delays. assert(d_decay != 0); assert(ivl_expr_type(d_rise) == IVL_EX_SIGNAL); assert(ivl_expr_type(d_fall) == IVL_EX_SIGNAL); assert(ivl_expr_type(d_decay) == IVL_EX_SIGNAL); fprintf(vvp_out, "L_%p .delay %u L_%p/d", cptr, dly_width, cptr); sig = ivl_expr_signal(d_rise); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(d_fall); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(d_decay); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0;\n", sig); } snprintf(tmp, sizeof tmp, "L_%p", cptr); result = strdup(tmp); } else { char tmp[64]; fprintf(vvp_out, "L_%p .functor BUFT 1, %s, " "C4<0>, C4<0>, C4<0>;\n", cptr, result); free(result); snprintf(tmp, sizeof tmp, "L_%p", cptr); result = strdup(tmp); } return result; } lpm = ivl_nexus_ptr_lpm(nptr); if (lpm) switch (ivl_lpm_type(lpm)) { case IVL_LPM_FF: case IVL_LPM_ABS: case IVL_LPM_ADD: case IVL_LPM_ARRAY: case IVL_LPM_CAST_INT2: case IVL_LPM_CAST_INT: case IVL_LPM_CAST_REAL: case IVL_LPM_CONCAT: case IVL_LPM_CONCATZ: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: case IVL_LPM_RE_AND: case IVL_LPM_RE_OR: case IVL_LPM_RE_XOR: case IVL_LPM_RE_NAND: case IVL_LPM_RE_NOR: case IVL_LPM_RE_XNOR: case IVL_LPM_SFUNC: case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTR: case IVL_LPM_SIGN_EXT: case IVL_LPM_SUB: case IVL_LPM_MULT: case IVL_LPM_MUX: case IVL_LPM_POW: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: case IVL_LPM_UFUNC: case IVL_LPM_PART_VP: case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */ case IVL_LPM_REPEAT: if (ivl_lpm_q(lpm) == nex) { char tmp[128]; snprintf(tmp, sizeof tmp, "L_%p", lpm); return strdup(tmp); } break; } fprintf(stderr, "vvp.tgt error: no input to nexus.\n"); assert(0); return strdup("C<z>"); }
static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex) { ivl_signal_t use_sig = 0; unsigned is_driver = 0; unsigned is_array = 0; int64_t array_idx = 0; unsigned idx, count = ivl_nexus_ptrs(nex); for (idx = 0; idx < count; idx += 1) { ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr); if (! sig) continue; if (ivl_signal_local(sig)) { /* If the local signal is another receiver skip it. */ if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) && (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) { continue; } assert(0); } /* We have a signal that can be used to find the name. */ if (scope == ivl_signal_scope(sig)) { if (use_sig) { /* Swap a receiver for a driver. */ if (is_driver && (ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) && (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) { use_sig = sig; is_driver = 0; if (ivl_signal_dimensions(sig) > 0) { is_array = 1; array_idx = ivl_nexus_ptr_pin(nex_ptr); array_idx += ivl_signal_array_base(sig); } continue; } // HERE: Which one should we use? For now it's the first one found. // I believe this needs to be solved (see the inout.v test). fprintf(stderr, "%s:%u: vlog95 warning: Duplicate " "name (%s", ivl_signal_file(sig), ivl_signal_lineno(sig), ivl_signal_basename(sig)); if (ivl_signal_dimensions(sig) > 0) { int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr); tmp_idx += ivl_signal_array_base(sig); fprintf(stderr, "[%"PRId64"]", tmp_idx); } fprintf(stderr, ") found for nexus (%s", ivl_signal_basename(use_sig)); if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx); fprintf(stderr, ")\n"); } else { use_sig = sig; /* This signal is a driver. */ if ((ivl_nexus_ptr_drive1(nex_ptr) != IVL_DR_HiZ) || (ivl_nexus_ptr_drive0(nex_ptr) != IVL_DR_HiZ)) { is_driver = 1; } if (ivl_signal_dimensions(sig) > 0) { is_array = 1; array_idx = ivl_nexus_ptr_pin(nex_ptr); array_idx += ivl_signal_array_base(sig); } } } } if (use_sig) { emit_id(ivl_signal_basename(use_sig)); if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx); return 1; } return 0; }
static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) { unsigned nptr_pin = ivl_nexus_ptr_pin(nptr); ivl_net_const_t cptr; ivl_net_logic_t lptr; ivl_signal_t sptr; ivl_lpm_t lpm; lptr = ivl_nexus_ptr_log(nptr); if (lptr && ((ivl_logic_type(lptr)==IVL_LO_BUFZ)||(ivl_logic_type(lptr)==IVL_LO_BUFT)) && (nptr_pin == 0)) do { if (! can_elide_bufz(lptr, nptr)) break; return strdup(draw_net_input(ivl_logic_pin(lptr, 1))); } while(0); if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLDOWN)) { return draw_net_pull(lptr, ivl_nexus_ptr_drive0(nptr), "0"); } if (lptr && (ivl_logic_type(lptr) == IVL_LO_PULLUP)) { return draw_net_pull(lptr, ivl_nexus_ptr_drive1(nptr), "1"); } if (lptr && (nptr_pin == 0)) { char tmp[128]; snprintf(tmp, sizeof tmp, "L_%p", lptr); return strdup(tmp); } sptr = ivl_nexus_ptr_sig(nptr); if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) { char tmp[128]; /* Input is a .var. This device may be a non-zero pin because it may be an array of reg vectors. */ snprintf(tmp, sizeof tmp, "v%p_%u", sptr, nptr_pin); if (ivl_signal_dimensions(sptr) > 0) { fprintf(vvp_out, "v%p_%u .array/port v%p, %u;\n", sptr, nptr_pin, sptr, nptr_pin); } return strdup(tmp); } cptr = ivl_nexus_ptr_con(nptr); if (cptr) { char tmp[64]; char *result = 0; ivl_expr_t d_rise, d_fall, d_decay; unsigned dly_width = 0; char *dly; /* Constants should have exactly 1 pin, with a literal value. */ assert(nptr_pin == 0); switch (ivl_const_type(cptr)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: case IVL_VT_STRING: if ((ivl_nexus_ptr_drive0(nptr) == IVL_DR_STRONG) && (ivl_nexus_ptr_drive1(nptr) == IVL_DR_STRONG)) { result = draw_C4_to_string(cptr); } else { result = draw_C8_to_string(cptr, ivl_nexus_ptr_drive0(nptr), ivl_nexus_ptr_drive1(nptr)); } dly_width = ivl_const_width(cptr); break; case IVL_VT_REAL: result = draw_Cr_to_string(ivl_const_real(cptr)); dly_width = 0; break; default: assert(0); break; } d_rise = ivl_const_delay(cptr, 0); d_fall = ivl_const_delay(cptr, 1); d_decay = ivl_const_delay(cptr, 2); dly = ""; if (d_rise != 0) { draw_delay(cptr, dly_width, 0, d_rise, d_fall, d_decay); dly = "/d"; } fprintf(vvp_out, "L_%p%s .functor BUFT 1, %s, C4<0>, C4<0>, C4<0>;\n", cptr, dly, result); free(result); snprintf(tmp, sizeof tmp, "L_%p", cptr); return strdup(tmp); } lpm = ivl_nexus_ptr_lpm(nptr); if (lpm) switch (ivl_lpm_type(lpm)) { case IVL_LPM_FF: case IVL_LPM_LATCH: case IVL_LPM_ABS: case IVL_LPM_ADD: case IVL_LPM_ARRAY: case IVL_LPM_CAST_INT2: case IVL_LPM_CAST_INT: case IVL_LPM_CAST_REAL: case IVL_LPM_CONCAT: case IVL_LPM_CONCATZ: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_WEQ: case IVL_LPM_CMP_WNE: case IVL_LPM_CMP_EQX: case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: case IVL_LPM_RE_AND: case IVL_LPM_RE_OR: case IVL_LPM_RE_XOR: case IVL_LPM_RE_NAND: case IVL_LPM_RE_NOR: case IVL_LPM_RE_XNOR: case IVL_LPM_SFUNC: case IVL_LPM_SHIFTL: case IVL_LPM_SHIFTR: case IVL_LPM_SIGN_EXT: case IVL_LPM_SUB: case IVL_LPM_MULT: case IVL_LPM_MUX: case IVL_LPM_POW: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: case IVL_LPM_UFUNC: case IVL_LPM_PART_VP: case IVL_LPM_PART_PV: /* NOTE: This is only a partial driver. */ case IVL_LPM_REPEAT: case IVL_LPM_SUBSTITUTE: if (ivl_lpm_q(lpm) == nex) { char tmp[128]; snprintf(tmp, sizeof tmp, "L_%p", lpm); return strdup(tmp); } break; } fprintf(stderr, "vvp.tgt error: no input to nexus.\n"); assert(0); return strdup("C<z>"); }
static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex) { unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { ivl_net_const_t con; ivl_net_logic_t logic; ivl_lpm_t lpm; ivl_signal_t sig; ivl_switch_t swt; ivl_branch_t bra; ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx); const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)]; const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)]; if ((sig = ivl_nexus_ptr_sig(ptr))) { fprintf(out, " SIG %s word=%u (%s0, %s1)", ivl_signal_name(sig), ivl_nexus_ptr_pin(ptr), dr0, dr1); if (ivl_signal_width(sig) != ivl_signal_width(net)) { fprintf(out, " (ERROR: Width=%u)", ivl_signal_width(sig)); stub_errors += 1; } if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) { fprintf(out, " (ERROR: data type mismatch)"); stub_errors += 1; } fprintf(out, "\n"); } else if ((logic = ivl_nexus_ptr_log(ptr))) { fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n", ivl_scope_name(ivl_logic_scope(logic)), ivl_logic_basename(logic), ivl_nexus_ptr_pin(ptr), dr0, dr1); } else if ((lpm = ivl_nexus_ptr_lpm(ptr))) { fprintf(out, " LPM %s.%s (%s0, %s1)\n", ivl_scope_name(ivl_lpm_scope(lpm)), ivl_lpm_basename(lpm), dr0, dr1); } else if ((swt = ivl_nexus_ptr_switch(ptr))) { fprintf(out, " SWITCH %s.%s\n", ivl_scope_name(ivl_switch_scope(swt)), ivl_switch_basename(swt)); } else if ((con = ivl_nexus_ptr_con(ptr))) { signal_nexus_const(net, ptr, con); } else if ((bra = ivl_nexus_ptr_branch(ptr))) { fprintf(out, " BRANCH %p terminal %u\n", bra, ivl_nexus_ptr_pin(ptr)); } else { fprintf(out, " ?[%u] (%s0, %s1)\n", ivl_nexus_ptr_pin(ptr), dr0, dr1); } } }