void show_switch(ivl_switch_t net) { const char*name = ivl_switch_basename(net); int has_enable = 0; ivl_nexus_t nexa, nexb; ivl_variable_type_t nex_type_a, nex_type_b; switch (ivl_switch_type(net)) { case IVL_SW_TRAN: fprintf(out, " tran %s", name); break; case IVL_SW_RTRAN: fprintf(out, " rtran %s", name); break; case IVL_SW_TRANIF0: fprintf(out, " tranif0 %s", name); has_enable = 1; break; case IVL_SW_RTRANIF0: fprintf(out, " rtranif0 %s", name); has_enable = 1; break; case IVL_SW_TRANIF1: fprintf(out, " tranif1 %s", name); has_enable = 1; break; case IVL_SW_RTRANIF1: fprintf(out, " rtranif1 %s", name); has_enable = 1; break; case IVL_SW_TRAN_VP: fprintf(out, " tran(VP wid=%u, part=%u, off=%u) %s", ivl_switch_width(net), ivl_switch_part(net), ivl_switch_offset(net), name); break; } fprintf(out, " island=%p\n", ivl_switch_island(net)); nexa = ivl_switch_a(net); nex_type_a = nexa? type_of_nexus(nexa) : IVL_VT_NO_TYPE; fprintf(out, " A: %p <type=%s>\n", nexa, data_type_string(nex_type_a)); nexb = ivl_switch_b(net); nex_type_b = nexb? type_of_nexus(nexb) : IVL_VT_NO_TYPE; fprintf(out, " B: %p <type=%s>\n", nexb, data_type_string(nex_type_b)); /* The A/B pins of the switch must be present, and must match. */ if (nex_type_a == IVL_VT_NO_TYPE) { fprintf(out, " A: ERROR: Type missing for pin A\n"); stub_errors += 1; } if (nex_type_b == IVL_VT_NO_TYPE) { fprintf(out, " B: ERROR: Type missing for pin B\n"); stub_errors += 1; } if (nex_type_a != nex_type_b) { fprintf(out, " A/B: ERROR: Type mismatch between pins A and B\n"); stub_errors += 1; } if (ivl_switch_type(net) == IVL_SW_TRAN_VP) { /* The TRAN_VP nodes are special in that the specific width matters for each port and should be exactly right for both. */ if (width_of_nexus(nexa) != ivl_switch_width(net)) { fprintf(out, " A: ERROR: part vector nexus " "width=%u, expecting width=%u\n", width_of_nexus(nexa), ivl_switch_width(net)); stub_errors += 1; } if (width_of_nexus(nexb) != ivl_switch_part(net)) { fprintf(out, " B: ERROR: part select nexus " "width=%u, expecting width=%u\n", width_of_nexus(nexb), ivl_switch_part(net)); stub_errors += 1; } } else { /* All other TRAN nodes will have matching vector widths, but the actual value doesn't matter. */ if (width_of_nexus(nexa) != width_of_nexus(nexb)) { fprintf(out, " A/B: ERROR: Width of ports don't match" ": A=%u, B=%u\n", width_of_nexus(nexa), width_of_nexus(nexb)); stub_errors += 1; } } if (has_enable) { ivl_nexus_t nexe = ivl_switch_enable(net); ivl_variable_type_t nexe_type = type_of_nexus(nexe); fprintf(out, " E: %p <type=%s>\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)); } } }
void draw_switch_in_scope(ivl_switch_t sw) { ivl_island_t island; ivl_nexus_t nex_a, nex_b, enable; const char*str_a, *str_b, *str_e; ivl_expr_t rise_exp = ivl_switch_delay(sw, 0); ivl_expr_t fall_exp = ivl_switch_delay(sw, 1); ivl_expr_t decay_exp= ivl_switch_delay(sw, 2); if ((rise_exp || fall_exp || decay_exp) && (!number_is_immediate(rise_exp, 64, 0) || number_is_unknown(rise_exp) || !number_is_immediate(fall_exp, 64, 0) || number_is_unknown(fall_exp) || !number_is_immediate(decay_exp, 64, 0) || number_is_unknown(decay_exp))) { fprintf(stderr, "%s:%u: error: Invalid tranif delay expression.\n", ivl_switch_file(sw), ivl_switch_lineno(sw)); vvp_errors += 1; } island = ivl_switch_island(sw); if (ivl_island_flag_test(island, 0) == 0) draw_tran_island(island); nex_a = ivl_switch_a(sw); assert(nex_a); str_a = draw_island_net_input(island, nex_a); nex_b = ivl_switch_b(sw); assert(nex_b); str_b = draw_island_net_input(island, nex_b); enable = ivl_switch_enable(sw); str_e = 0; char str_e_buf[4 + 2*sizeof(void*)]; if (enable && rise_exp) { assert(fall_exp && decay_exp); /* If the enable has a delay, then generate a .delay node to delay the input by the specified amount. Do the delay outside of the island so that the island processing doesn't have to deal with it. */ const char*raw = draw_net_input(enable); snprintf(str_e_buf, sizeof str_e_buf, "p%p", sw); str_e = str_e_buf; fprintf(vvp_out, "%s/d .delay 1 " "(%" PRIu64 ",%" PRIu64 ",%" PRIu64 ") %s;\n", str_e, get_number_immediate64(rise_exp), get_number_immediate64(fall_exp), get_number_immediate64(decay_exp), raw); fprintf(vvp_out, "%s .import I%p, %s/d;\n", str_e, island, str_e); } else if (enable) { str_e = draw_island_net_input(island, enable); } switch (ivl_switch_type(sw)) { case IVL_SW_TRAN: fprintf(vvp_out, " .tran"); break; case IVL_SW_TRANIF0: fprintf(vvp_out, " .tranif0"); break; case IVL_SW_TRANIF1: fprintf(vvp_out, " .tranif1"); break; case IVL_SW_TRAN_VP: fprintf(vvp_out, " .tranvp %u %u %u,", ivl_switch_width(sw), ivl_switch_part(sw), ivl_switch_offset(sw)); break; default: fprintf(stderr, "%s:%u: tgt-vvp sorry: resistive switch modeling " "is not currently supported.\n", ivl_switch_file(sw), ivl_switch_lineno(sw)); vvp_errors += 1; return; } fprintf(vvp_out, " I%p, %s %s", island, str_a, str_b); if (enable) { fprintf(vvp_out, ", %s", str_e); } fprintf(vvp_out, ";\n"); }