/* * This function scans the netlist for all the pin assignments that * are fixed by a PAD attribute. Search the scopes recursively, * looking for signals that may have PAD attributes. */ int get_pad_bindings(ivl_scope_t net, void*x) { unsigned idx; int rc = ivl_scope_children(net, get_pad_bindings, 0); if (rc) return rc; for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) { ivl_signal_t sig; const char*pad; int pin; sig = ivl_scope_sig(net, idx); pad = ivl_signal_attr(sig, "PAD"); if (pad == 0) continue; pin = strtol(pad+1, 0, 10); if ((pin == 0) || (pin > pins)) { printf("%s: Invalid PAD assignment: %s\n", ivl_signal_name(sig), pad); error_count += 1; continue; } assert(ivl_signal_pins(sig) == 1); if (bind_pin[pin-1].nexus) { if (bind_pin[pin-1].nexus != ivl_signal_pin(sig, 0)) { printf("%s: Unconnected signals share pin %d\n", ivl_signal_name(sig), pin); error_count += 1; } continue; } bind_pin[pin-1].nexus = ivl_signal_pin(sig, 0); } 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)); } }
/* * 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 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); } } }