void show_constant(ivl_net_const_t net) { assert(net); fprintf(out, "constant "); switch (ivl_const_type(net)) { case IVL_VT_BOOL: case IVL_VT_LOGIC: { const char*bits = ivl_const_bits(net); unsigned idx; assert(bits); for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1) fprintf(out, "%c", bits[idx]); } break; case IVL_VT_REAL: fprintf(out, "%f", ivl_const_real(net)); break; default: fprintf(out, "<unsupported type>"); break; } fprintf(out, " at %s:%u\n", ivl_const_file(net), ivl_const_lineno(net)); }
static void emit_number_as_string(ivl_net_const_t net_const) { const char *bits = ivl_const_bits(net_const); unsigned count = ivl_const_width(net_const); int idx; assert((count % 8) == 0); fprintf(vlog_out, "\""); for (idx = (int)count-1; idx >= 0; idx -= 8) { unsigned bit; char val = 0; for (bit = 0; bit < 8; bit += 1) { val |= (bits[idx-bit] == '1') ? 1 << (7-bit) : 0x00; } /* Skip any NULL bytes. */ if (val == 0) continue; /* Print some values that can be escaped. */ if (val == '"') fprintf(vlog_out, "\\\""); else if (val == '\\') fprintf(vlog_out, "\\\\"); else if (val == '\n') fprintf(vlog_out, "\\n"); else if (val == '\t') fprintf(vlog_out, "\\t"); /* Print the printable characters. */ else if (isprint((int)val)) fprintf(vlog_out, "%c", val); /* Print the non-printable characters as an octal escape. */ else fprintf(vlog_out, "\\%03o", val); } fprintf(vlog_out, "\""); }
void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t net_const) { ivl_scope_t const_scope = ivl_const_scope(net_const); unsigned idx, count, lineno; const char *file; count = ivl_scope_params(const_scope); file = ivl_const_file(net_const); lineno = ivl_const_lineno(net_const); /* Look to see if the constant matches a parameter in its scope. */ for (idx = 0; idx < count; idx += 1) { ivl_parameter_t par = ivl_scope_param(const_scope, idx); if (lineno != ivl_parameter_lineno(par)) continue; if (strcmp(file, ivl_parameter_file(par)) == 0) { /* Check that the appropriate expression bits match the * original parameter bits. */ // HERE: Verify that the values match and then print the name. // Does this work with out of scope references? Check real parameters. emit_id(ivl_parameter_basename(par)); return; } } /* If the scopes don't match then we assume this is an empty port. */ if (const_scope != scope) { /* This constant could really be from an input port. */ if (emit_as_input(scope, net_const)) return; fprintf(vlog_out, "/* Empty */"); return; } switch (ivl_const_type(net_const)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: emit_number(ivl_const_bits(net_const), ivl_const_width(net_const), ivl_const_signed(net_const), ivl_const_file(net_const), ivl_const_lineno(net_const)); break; case IVL_VT_STRING: emit_number_as_string(net_const); break; case IVL_VT_REAL: emit_real_number(ivl_const_real(net_const)); break; default: fprintf(vlog_out, "<invalid>"); fprintf(stderr, "%s:%u: vlog95 error: Unknown constant type " "(%d).\n", ivl_const_file(net_const), ivl_const_lineno(net_const), (int)ivl_const_type(net_const)); vlog_errors += 1; break; } }
static char* draw_C8_to_string(ivl_net_const_t cptr, ivl_drive_t dr0, ivl_drive_t dr1) { size_t nresult = 5 + 3*ivl_const_width(cptr); char*result = malloc(nresult); const char*bits = ivl_const_bits(cptr); unsigned idx; char dr0c = "01234567"[dr0]; char dr1c = "01234567"[dr1]; char*dp = result; strcpy(dp, "C8<"); dp += strlen(dp); for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) { switch (bits[ivl_const_width(cptr)-idx-1]) { case '0': *dp++ = dr0c; *dp++ = dr0c; *dp++ = '0'; break; case '1': *dp++ = dr1c; *dp++ = dr1c; *dp++ = '1'; break; case 'x': case 'X': *dp++ = dr0c; *dp++ = dr1c; *dp++ = 'x'; break; case 'z': case 'Z': *dp++ = '0'; *dp++ = '0'; *dp++ = 'z'; break; default: assert(0); break; } assert(dp >= result); assert((unsigned)(dp - result) < nresult); } strcpy(dp, ">"); return result; }
static void lpm_show_constant(ivl_net_const_t net) { edif_cell_t cell0 = edif_xlibrary_findcell(xlib, "cell0"); edif_cell_t cell1 = edif_xlibrary_findcell(xlib, "cell1"); edif_cellref_t ref0 = 0, ref1 = 0; const char*bits; unsigned idx; if (cell0 == 0) { cell0 = edif_xcell_create(xlib, "cell0", 1); edif_cell_portconfig(cell0, 0, "Result0", IVL_SIP_OUTPUT); edif_cell_pstring(cell0, "LPM_Type", "LPM_CONSTANT"); edif_cell_pinteger(cell0, "LPM_Width", 1); edif_cell_pinteger(cell0, "LPM_CValue", 0); } if (cell1 == 0) { cell1 = edif_xcell_create(xlib, "cell1", 1); edif_cell_portconfig(cell1, 0, "Result0", IVL_SIP_OUTPUT); edif_cell_pstring(cell1, "LPM_Type", "LPM_CONSTANT"); edif_cell_pinteger(cell1, "LPM_Width", 1); edif_cell_pinteger(cell1, "LPM_CValue", 1); } bits = ivl_const_bits(net); for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { if (bits[idx] == '1') { if (ref1 == 0) ref1 = edif_cellref_create(edf, cell1); } else { if (ref0 == 0) ref0 = edif_cellref_create(edf, cell0); } } for (idx = 0 ; idx < ivl_const_pins(net) ; idx += 1) { edif_joint_t jnt; jnt = edif_joint_of_nexus(edf, ivl_const_pin(net,idx)); if (bits[idx] == '1') edif_add_to_joint(jnt, ref1, 0); else edif_add_to_joint(jnt, ref0, 0); } }
/* * This function is used by the show_signal to dump a constant value * that is connected to the signal. While we are here, check that the * value is consistent with the signal itself. */ static void signal_nexus_const(ivl_signal_t sig, ivl_nexus_ptr_t ptr, ivl_net_const_t con) { const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)]; const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)]; const char*bits; unsigned idx, width = ivl_const_width(con); fprintf(out, " const-"); switch (ivl_const_type(con)) { case IVL_VT_BOOL: case IVL_VT_LOGIC: bits = ivl_const_bits(con); assert(bits); for (idx = 0 ; idx < width ; idx += 1) { fprintf(out, "%c", bits[width-idx-1]); } break; case IVL_VT_REAL: fprintf(out, "%f", ivl_const_real(con)); break; default: fprintf(out, "????"); break; } fprintf(out, " (%s0, %s1, width=%u)\n", dr0, dr1, width); if (ivl_signal_width(sig) != width) { fprintf(out, "ERROR: Width of signal does not match " "width of connected constant vector.\n"); stub_errors += 1; } int drive_type_ok = check_signal_drive_type(ivl_signal_data_type(sig), ivl_const_type(con)); if (! drive_type_ok) { fprintf(out, "ERROR: Signal data type does not match" " literal type.\n"); stub_errors += 1; } }
static void show_design_consts_xnf(ivl_design_t des) { unsigned idx; for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) { unsigned pin; ivl_net_const_t net = ivl_design_const(des, idx); const char*val = ivl_const_bits(net); for (pin = 0 ; pin < ivl_const_pins(net) ; pin += 1) { ivl_nexus_t nex = ivl_const_pin(net, pin); fprintf(xnf, "PWR,%c,%s\n", val[pin], xnf_mangle_nexus_name(nex)); } } }
static void edif_show_consts(ivl_design_t des) { unsigned idx; char jbuf[128]; for (idx = 0 ; idx < ivl_design_consts(des) ; idx += 1) { unsigned pin; ivl_net_const_t net = ivl_design_const(des, idx); const char*val = ivl_const_bits(net); for (pin = 0 ; pin < ivl_const_pins(net) ; pin += 1) { ivl_nexus_t nex = ivl_const_pin(net, pin); const char*name; const char*port; edif_uref += 1; switch (val[pin]) { case '0': name = "GND"; port = "GROUND"; break; case '1': name = "VCC"; port = "VCC"; break; default: name = "???"; port = "?"; break; } fprintf(xnf, "(instance U%u " "(viewRef net" " (cellRef %s (libraryRef VIRTEX))))\n", edif_uref, name); sprintf(jbuf, "(portRef %s (instanceRef U%u))", port, edif_uref); edif_set_nexus_joint(nex, jbuf); } } }
static char* draw_C4_to_string(ivl_net_const_t cptr) { const char*bits = ivl_const_bits(cptr); unsigned idx; size_t result_len = 5 + ivl_const_width(cptr); char*result = malloc(result_len); char*dp = result; strcpy(dp, "C4<"); dp += strlen(dp); for (idx = 0 ; idx < ivl_const_width(cptr) ; idx += 1) { char bitchar = bits[ivl_const_width(cptr)-idx-1]; *dp++ = bitchar; assert(dp >= result); assert((unsigned)(dp - result) < result_len); } strcpy(dp, ">"); return result; }
// Build the design hierarchy. int build_hierarchy(ivl_scope_t scope, void* cd) { int return_code; unsigned i, j; indent(); fprintf(output, "(scope "); quoted_string(ivl_scope_tname(scope)); fprintf(output, " "); quoted_string(ivl_scope_basename(scope)); fprintf(output, " (\n"); // Constants (root scope only) if (! level) for (i = 0; i < ivl_design_consts(design); i++) { ivl_net_const_t constant = ivl_design_const(design, i); const char* bits = ivl_const_bits(constant); unsigned pins = ivl_const_pins(constant); unsigned id = new_id(); indent(); fprintf(output, " (const %i \"", id); for (j = pins - 1; j < pins; j--) fprintf(output, "%c", bits[j]); fprintf(output, "\")\n"); for (j = 0; j < pins; j++) create_bit_select(id_of_nexus(ivl_const_pin(constant, j), 1), pins, j, id); } // Parameters for (i = 0; i < ivl_scope_params(scope); i++) { ivl_parameter_t param = ivl_scope_param(scope, i); ivl_expr_t param_value = ivl_parameter_expr(param); unsigned width = ivl_expr_width(param_value); const char* bits; unsigned id = new_id(); indent(); fprintf(output, " (const %i \"", id); switch (ivl_expr_type(param_value)) { case IVL_EX_STRING : bits = ivl_expr_string(param_value); break; case IVL_EX_NUMBER : bits = ivl_expr_bits(param_value); break; default : fprintf(output, "** ERROR: Unknown parameter type."); return -1; } for (j = width - 1; j < width; j--) fprintf(output, "%c", bits[j]); fprintf(output, "\")\n"); indent(); fprintf(output, " (name %i ", new_id()); quoted_string(ivl_parameter_basename(param)); fprintf(output, " %i %i)\n", width, id); } // Signals for (i = 0; i < ivl_scope_sigs(scope); i++) { ivl_signal_t sig = ivl_scope_sig(scope, i); unsigned pins = ivl_signal_pins(sig); ivl_signal_port_t type = ivl_signal_port(sig); const char* name = ivl_signal_basename(sig); unsigned id; if (! level && type == IVL_SIP_INPUT) { id = new_id(); fprintf(output, " (input %i \"%s\" %i)\n", id, name, pins); for (j = 0; j < pins; j++) create_bit_select(id_of_nexus(ivl_signal_pin(sig, j), 1), pins, j, id); } else if (! level && type == IVL_SIP_INOUT) { printf("** ERROR: Inout ports not supported.\n"); } else if (! level && type == IVL_SIP_OUTPUT) { id = id_of_nexus(ivl_signal_pin(sig, 0), 0); for (j = 1; j < pins; j++) { id = create_bit_concat(id, j, ivl_signal_pin(sig, j)); } fprintf(output, " (output %i \"%s\" %i %i)\n", new_id(), name, pins, id); } else { id = id_of_nexus(ivl_signal_pin(sig, 0), 0); for (j = 1; j < pins; j++) { id = create_bit_concat(id, j, ivl_signal_pin(sig, j)); } indent(); fprintf(output, " (name %i ", new_id()); //XXX Why is "_s22" getting named? quoted_string(name); fprintf(output, " %i %i)\n", pins, id); } } // Logic for (i = 0; i < ivl_scope_logs(scope); i++) { unsigned id; ivl_net_logic_t log = ivl_scope_log(scope, i); switch (ivl_logic_type(log)) { case IVL_LO_BUF: indent(); fprintf(output, " (buf %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0)); break; case IVL_LO_NOT: indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id_of_nexus(ivl_logic_pin(log, 1), 0)); break; case IVL_LO_AND: indent(); create_multi_gate("and ", id_of_nexus(ivl_logic_pin(log, 0), 1), log); break; case IVL_LO_NAND: id = new_id(); indent(); create_multi_gate("and ", id, log); indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id); break; case IVL_LO_XOR: indent(); create_multi_gate("xor ", id_of_nexus(ivl_logic_pin(log, 0), 1), log); break; case IVL_LO_XNOR: id = new_id(); indent(); create_multi_gate("xor ", id, log); indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id); break; case IVL_LO_OR: indent(); create_multi_gate("or ", id_of_nexus(ivl_logic_pin(log, 0), 1), log); break; case IVL_LO_NOR: id = new_id(); indent(); create_multi_gate("or ", id, log); indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_logic_pin(log, 0), 1), id); break; default: printf("** ERROR: Unsupported logic type: %i.\n", ivl_logic_type(log)); return -1; } } // LPMs for (i = 0; i < ivl_scope_lpms(scope); i++) { ivl_lpm_t lpm = ivl_scope_lpm(scope, i); ivl_lpm_type_t lpm_t = ivl_lpm_type(lpm); unsigned width = ivl_lpm_width(lpm); unsigned selects; unsigned size; unsigned id, id1, id2, id3; switch (lpm_t) { case IVL_LPM_ADD: id = new_id(); id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); indent(); fprintf(output, " (add %i %i %i %i)\n", id, width, id1, id2); create_split_lpm_q(lpm, id); break; case IVL_LPM_SUB: id = new_id(); id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); indent(); fprintf(output, " (sub %i %i %i %i)\n", id, width, id1, id2); create_split_lpm_q(lpm, id); break; case IVL_LPM_MULT: id = new_id(); id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); indent(); fprintf(output, " (mul %i %i %i %i)\n", id, width, id1, id2); create_split_lpm_q(lpm, id); break; case IVL_LPM_CMP_EQ: id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); indent(); fprintf(output, " (eq %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id1, id2); break; case IVL_LPM_CMP_NE: id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); id = new_id(); indent(); fprintf(output, " (eq %i %i %i %i)\n", id, width, id1, id2); indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id); break; case IVL_LPM_CMP_GT: // XXX Check for signed. id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); indent(); fprintf(output, " (lt %i %i %i %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), width, id2, id1); break; case IVL_LPM_CMP_GE: // XXX Check for signed. id1 = create_concat_lpm_data(lpm); id2 = create_concat_lpm_datab(lpm); id = new_id(); indent(); fprintf(output, " (lt %i %i %i %i)\n", id, width, id1, id2); indent(); fprintf(output, " (not %i 1 %i)\n", id_of_nexus(ivl_lpm_q(lpm, 0), 1), id); break; case IVL_LPM_FF: { ivl_nexus_t async_clr = ivl_lpm_async_clr(lpm); ivl_nexus_t async_set = ivl_lpm_async_set(lpm); ivl_nexus_t sync_clr = ivl_lpm_sync_clr(lpm); ivl_nexus_t sync_set = ivl_lpm_sync_set(lpm); ivl_nexus_t clk = ivl_lpm_clk(lpm); ivl_nexus_t enable = ivl_lpm_enable(lpm); if (async_set || sync_set) { perror("** ERROR: Does not support registers with async or sync sets.\n"); return -1; } id = new_id(); id1 = create_concat_lpm_data(lpm); if (enable) { id2 = new_id(); indent(); fprintf(output, " (mux %i %i %i %i %i)\n", id2, width, id_of_nexus(enable, 0), id, id1); id1 = id2; } if (sync_clr) { id2 = new_id(); id3 = new_id(); indent(); fprintf(output, " (const %i \"", id3); for (j = 0; j < width; j++) fprintf(output, "0"); fprintf(output, "\")\n"); indent(); fprintf(output, " (mux %i %i %i %i %i)\n", id2, width, id_of_nexus(sync_clr, 0), id1, id3); id1 = id2; } // XXX Default to posedge sensitivity. if (async_clr) { indent(); fprintf(output, " (ffc %i %i %i %i %i)\n", id, width, id_of_nexus(async_clr, 0), id_of_nexus(clk, 0), id1); } else { indent(); fprintf(output, " (ff %i %i %i %i)\n", id, width, id_of_nexus(clk, 0), id1); } create_split_lpm_q(lpm, id); } break; case IVL_LPM_MUX: { unsigned t = 1; selects = ivl_lpm_selects(lpm); size = ivl_lpm_size(lpm); for (j = 0; j < selects; j++) t = t * 2; assert(t == size); // General case. id = create_mux(lpm, selects, 0); create_split_lpm_q(lpm, id); } break; default: perror("** ERROR: Unsupported LPM type.\n"); return -1; } } level = level + 1; return_code = ivl_scope_children(scope, build_hierarchy, 0); level = level - 1; if (! level) delete_nexus_table(nexus_table); indent(); fprintf(output, "))\n"); return return_code; }