/* * Handle a PART SELECT PV device. Generate a .part/pv node that * includes the part input, and the geometry of the part. */ static void draw_lpm_part_pv(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); unsigned base = ivl_lpm_base(net); unsigned signal_width = width_of_nexus(ivl_lpm_q(net,0)); fprintf(vvp_out, "L_%p .part/pv %s", net, draw_net_input(ivl_lpm_data(net, 0))); fprintf(vvp_out, ", %u, %u, %u;\n", base, width, signal_width); }
/* * Handle a PART SELECT device. This has a single input and output, * plus an optional extra input that is a non-constant base. */ static void draw_lpm_part(ivl_lpm_t net) { unsigned width, base; ivl_nexus_t sel; const char*dly = draw_lpm_output_delay(net); width = ivl_lpm_width(net); base = ivl_lpm_base(net); sel = ivl_lpm_data(net,1); if (sel == 0) { fprintf(vvp_out, "L_%p%s .part %s", net, dly, draw_net_input(ivl_lpm_data(net, 0))); fprintf(vvp_out, ", %u, %u;\n", base, width); } else { const char*sel_symbol = draw_net_input(sel); fprintf(vvp_out, "L_%p%s .part/v %s", net, dly, draw_net_input(ivl_lpm_data(net,0))); fprintf(vvp_out, ", %s", sel_symbol); fprintf(vvp_out, ", %u;\n", width); } }
static void show_lpm_part(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); unsigned base = ivl_lpm_base(net); ivl_nexus_t sel = ivl_lpm_data(net,1); const char*part_type_string = ""; switch (ivl_lpm_type(net)) { case IVL_LPM_PART_VP: part_type_string = "VP"; break; case IVL_LPM_PART_PV: part_type_string = "PV"; break; default: break; } fprintf(out, " LPM_PART_%s %s: <width=%u, base=%u, signed=%d>\n", part_type_string, ivl_lpm_basename(net), width, base, ivl_lpm_signed(net)); fprintf(out, " O: %p\n", ivl_lpm_q(net)); fprintf(out, " I: %p\n", ivl_lpm_data(net,0)); if (sel != 0) { fprintf(out, " S: %p\n", sel); if (base != 0) { fprintf(out, " ERROR: Part select has base AND selector\n"); stub_errors += 1; } } /* The compiler must assure that the base plus the part select width fits within the input to the part select. */ switch (ivl_lpm_type(net)) { case IVL_LPM_PART_VP: if (width_of_nexus(ivl_lpm_data(net,0)) < (width+base)) { fprintf(out, " ERROR: Part select is out of range." " Data nexus width=%u, width+base=%u\n", width_of_nexus(ivl_lpm_data(net,0)), width+base); stub_errors += 1; } if (width_of_nexus(ivl_lpm_q(net)) != width) { fprintf(out, " ERROR: Part select input mismatch." " Nexus width=%u, expect width=%u\n", width_of_nexus(ivl_lpm_q(net)), width); stub_errors += 1; } break; case IVL_LPM_PART_PV: if (width_of_nexus(ivl_lpm_q(net)) < (width+base)) { fprintf(out, " ERROR: Part select is out of range." " Target nexus width=%u, width+base=%u\n", width_of_nexus(ivl_lpm_q(net)), width+base); stub_errors += 1; } if (width_of_nexus(ivl_lpm_data(net,0)) != width) { fprintf(out, " ERROR: Part select input mismatch." " Nexus width=%u, expect width=%u\n", width_of_nexus(ivl_lpm_data(net,0)), width); stub_errors += 1; } break; default: assert(0); } }