static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir) { ivl_nexus_t nex; unsigned width = ivl_lpm_width(net); fprintf(out, " LPM_SHIFT%s %s: <width=%u, %ssigned>\n", shift_dir, ivl_lpm_basename(net), width, ivl_lpm_signed(net)? "" : "un"); nex = ivl_lpm_q(net); fprintf(out, " Q: %p\n", nex); if (width != width_of_nexus(nex)) { fprintf(out, " ERROR: Q output nexus width=%u " "does not match part width\n", width_of_nexus(nex)); stub_errors += 1; } nex = ivl_lpm_data(net, 0); fprintf(out, " D: %p\n", nex); if (width != width_of_nexus(nex)) { fprintf(out, " ERROR: Q output nexus width=%u " "does not match part width\n", width_of_nexus(nex)); stub_errors += 1; } nex = ivl_lpm_data(net, 1); fprintf(out, " S: %p <width=%u>\n", nex, width_of_nexus(nex)); }
/* IVL_LPM_CMP_GT * This LPM node supports two-input compare. */ static void show_lpm_cmp_gt(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); fprintf(out, " LPM_CMP_GT %s: <width=%u %s>\n", ivl_lpm_basename(net), width, ivl_lpm_signed(net)? "signed" : "unsigned"); fprintf(out, " O: %p\n", ivl_lpm_q(net)); fprintf(out, " A: %p\n", ivl_lpm_data(net,0)); fprintf(out, " B: %p\n", ivl_lpm_data(net,1)); check_cmp_widths(net); }
static void draw_lpm_cast_real(ivl_lpm_t net) { const char*src_table[1]; const char*dly; const char*is_signed = ""; draw_lpm_data_inputs(net, 0, 1, src_table); dly = draw_lpm_output_delay(net); if (ivl_lpm_signed(net)) is_signed = ".s"; fprintf(vvp_out, "L_%p%s .cast/real%s %s;\n", net, dly, is_signed, src_table[0]); }
static void draw_lpm_shiftl(ivl_lpm_t net) { unsigned width = ivl_lpm_width(net); const char* signed_flag = ivl_lpm_signed(net)? "s" : ""; const char*dly = draw_lpm_output_delay(net); if (ivl_lpm_type(net) == IVL_LPM_SHIFTR) fprintf(vvp_out, "L_%p%s .shift/r%s %u", net, dly, signed_flag, width); else fprintf(vvp_out, "L_%p%s .shift/l %u", net, dly, width); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 0))); fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net, 1))); fprintf(vvp_out, ";\n"); }
static void draw_lpm_cmp(ivl_lpm_t net) { const char*src_table[2]; unsigned width; const char*type = ""; const char*signed_string = ivl_lpm_signed(net)? ".s" : ""; ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0)); ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1)); ivl_variable_type_t dtc = IVL_VT_LOGIC; const char*dly; if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL) dtc = IVL_VT_REAL; width = ivl_lpm_width(net); switch (ivl_lpm_type(net)) { case IVL_LPM_CMP_EEQ: assert(dtc != IVL_VT_REAL); /* Should never get here! */ type = "eeq"; signed_string = ""; break; case IVL_LPM_CMP_EQ: if (dtc == IVL_VT_REAL) type = "eq.r"; else type = "eq"; signed_string = ""; break; case IVL_LPM_CMP_GE: if (dtc == IVL_VT_REAL) { type = "ge.r"; signed_string = ""; } else type = "ge"; break; case IVL_LPM_CMP_GT: if (dtc == IVL_VT_REAL) { type = "gt.r"; signed_string = ""; } else type = "gt"; break; case IVL_LPM_CMP_NE: if (dtc == IVL_VT_REAL) type = "ne.r"; else type = "ne"; signed_string = ""; break; case IVL_LPM_CMP_NEE: assert(dtc != IVL_VT_REAL); /* Should never get here! */ type = "nee"; signed_string = ""; break; default: assert(0); } draw_lpm_data_inputs(net, 0, 2, src_table); dly = draw_lpm_output_delay(net); fprintf(vvp_out, "L_%p%s .cmp/%s%s %u, %s, %s;\n", net, dly, type, signed_string, width, src_table[0], src_table[1]); }
static void draw_lpm_add(ivl_lpm_t net) { const char*src_table[2]; unsigned width; const char*type = ""; ivl_variable_type_t dta = data_type_of_nexus(ivl_lpm_data(net,0)); ivl_variable_type_t dtb = data_type_of_nexus(ivl_lpm_data(net,1)); ivl_variable_type_t dto = IVL_VT_LOGIC; const char*dly; if (dta == IVL_VT_REAL || dtb == IVL_VT_REAL) dto = IVL_VT_REAL; width = ivl_lpm_width(net); switch (ivl_lpm_type(net)) { case IVL_LPM_ADD: if (dto == IVL_VT_REAL) type = "sum.r"; else type = "sum"; break; case IVL_LPM_SUB: if (dto == IVL_VT_REAL) type = "sub.r"; else type = "sub"; break; case IVL_LPM_MULT: if (dto == IVL_VT_REAL) type = "mult.r"; else type = "mult"; break; case IVL_LPM_DIVIDE: if (dto == IVL_VT_REAL) type = "div.r"; else if (ivl_lpm_signed(net)) type = "div.s"; else type = "div"; break; case IVL_LPM_MOD: if (dto == IVL_VT_REAL) type = "mod.r"; else if (ivl_lpm_signed(net)) type = "mod.s"; else type = "mod"; break; case IVL_LPM_POW: if (dto == IVL_VT_REAL) type = "pow.r"; else if (ivl_lpm_signed(net)) type = "pow.s"; else type = "pow"; break; default: assert(0); } draw_lpm_data_inputs(net, 0, 2, src_table); dly = draw_lpm_output_delay(net); fprintf(vvp_out, "L_%p%s .arith/%s %u, %s, %s;\n", net, dly, type, width, src_table[0], src_table[1]); }
static void show_lpm(ivl_lpm_t net) { switch (ivl_lpm_type(net)) { case IVL_LPM_ABS: show_lpm_abs(net); break; case IVL_LPM_ADD: show_lpm_add(net); break; case IVL_LPM_ARRAY: show_lpm_array(net); break; case IVL_LPM_CAST_INT: show_lpm_cast_int(net); break; case IVL_LPM_CAST_REAL: show_lpm_cast_real(net); break; case IVL_LPM_DIVIDE: show_lpm_divide(net); break; case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_NEE: show_lpm_cmp_eeq(net); break; case IVL_LPM_FF: show_lpm_ff(net); break; case IVL_LPM_CMP_GE: show_lpm_cmp_ge(net); break; case IVL_LPM_CMP_GT: show_lpm_cmp_gt(net); break; case IVL_LPM_CMP_NE: show_lpm_cmp_ne(net); break; case IVL_LPM_CONCAT: show_lpm_concat(net); break; case IVL_LPM_RE_AND: case IVL_LPM_RE_NAND: case IVL_LPM_RE_NOR: case IVL_LPM_RE_OR: case IVL_LPM_RE_XOR: case IVL_LPM_RE_XNOR: show_lpm_re(net); break; case IVL_LPM_SHIFTL: show_lpm_shift(net, "L"); break; case IVL_LPM_SIGN_EXT: show_lpm_sign_ext(net); break; case IVL_LPM_SHIFTR: show_lpm_shift(net, "R"); break; case IVL_LPM_SUB: show_lpm_sub(net); break; case IVL_LPM_MOD: show_lpm_mod(net); break; case IVL_LPM_MULT: show_lpm_mult(net); break; case IVL_LPM_MUX: show_lpm_mux(net); break; case IVL_LPM_PART_VP: case IVL_LPM_PART_PV: show_lpm_part(net); break; case IVL_LPM_REPEAT: show_lpm_repeat(net); break; case IVL_LPM_SFUNC: show_lpm_sfunc(net); break; case IVL_LPM_UFUNC: show_lpm_ufunc(net); break; default: fprintf(out, " LPM(%d) %s: <width=%u, signed=%d>\n", ivl_lpm_type(net), ivl_lpm_basename(net), ivl_lpm_width(net), ivl_lpm_signed(net)); } }
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); } }