/* * Draw a single logic gate. Escape the name so that it is preserved * completely. This drawing is happening in the root scope so signal * references can remain hierarchical. */ static int draw_logic(ivl_net_logic_t net) { unsigned npins, idx; const char*name = ivl_logic_name(net); switch (ivl_logic_type(net)) { case IVL_LO_AND: fprintf(out, " and \\%s (", name); break; case IVL_LO_BUF: fprintf(out, " buf \\%s (", name); break; case IVL_LO_OR: fprintf(out, " or \\%s (", name); break; case IVL_LO_XOR: fprintf(out, " xor \\%s (", name); break; default: fprintf(out, "STUB: %s: unsupported gate\n", name); return -1; } draw_nexus(ivl_logic_pin(net, 0)); npins = ivl_logic_pins(net); for (idx = 1 ; idx < npins ; idx += 1) { fprintf(out, ", "); draw_nexus(ivl_logic_pin(net,idx)); } fprintf(out, ");\n"); return 0; }
/* * Pick off the cases where there is a Virtex specific implementation * that is better then the generic Xilinx implementation. Route the * remaining to the base xilinx_logic implementation. */ void virtex_logic(ivl_net_logic_t net) { /* Nothing I can do if the user expresses a specific opinion. The cellref attribute forces me to let the base xilinx_logic take care of it. */ if (ivl_logic_attr(net, "cellref")) { xilinx_logic(net); return; } switch (ivl_logic_type(net)) { case IVL_LO_OR: case IVL_LO_NOR: if (ivl_logic_pins(net) <= 5) { xilinx_logic(net); } else { virtex_or_wide(net); } break; default: xilinx_logic(net); break; } }
static void draw_udp_in_scope(ivl_net_logic_t lptr) { unsigned pdx; ivl_udp_t udp = ivl_logic_udp(lptr); static ivl_udp_t *udps = 0x0; static int nudps = 0; int i; for (i=0; i<nudps; i++) if (udps[i] == udp) break; if (i >= nudps) { udps = realloc(udps, (nudps+1)*sizeof(ivl_udp_t)); assert(udps); udps[nudps++] = udp; draw_udp_def(udp); } fprintf(vvp_out, "L_%p .udp", lptr); fprintf(vvp_out, " UDP_%s", vvp_mangle_id(ivl_udp_name(udp))); draw_delay(lptr); for (pdx = 1 ; pdx < ivl_logic_pins(lptr) ; pdx += 1) { ivl_nexus_t nex = ivl_logic_pin(lptr, pdx); /* Unlike other logic gates, primitives may have unconnected inputs. The proper behavior is to attach a HiZ to the port. */ if (nex == 0) { assert(ivl_logic_width(lptr) == 1); fprintf(vvp_out, ", C4<z>"); } else { fprintf(vvp_out, ", %s", draw_net_input(nex)); } } fprintf(vvp_out, ";\n"); }
// Repeated gates. void create_multi_gate(const char* gate, unsigned id, ivl_net_logic_t logic) { unsigned width = ivl_logic_pins(logic); unsigned id1 = id_of_nexus(ivl_logic_pin(logic, 1), 0); if (width == 2) { indent(); fprintf(output, " (buf %i 1 %i)\n", id, id1); } else { unsigned i; unsigned id2; for (i = 2; i < width; i++) { id2 = (i == width - 1) ? id : new_id(); indent(); fprintf(output, " (%s %i 1 %i %i)\n", gate, id2, id1, id_of_nexus(ivl_logic_pin(logic, i), 0)); id1 = id2; } } }
static void hookup_logic_gate(ivl_net_logic_t net, edif_cell_t cell) { unsigned pin, idx; edif_joint_t jnt; edif_cellref_t ref = edif_cellref_create(edf, cell); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); pin = edif_cell_port_byname(cell, "Result0"); edif_add_to_joint(jnt, ref, pin); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char name[32]; jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx)); sprintf(name, "Data%ux0", idx-1); pin = edif_cell_port_byname(cell, name); edif_add_to_joint(jnt, ref, pin); } }
static void lpm_logic(ivl_net_logic_t net) { edif_cell_t cell; edif_cellref_t ref; edif_joint_t jnt; switch (ivl_logic_type(net)) { case IVL_LO_BUFZ: case IVL_LO_BUF: assert(ivl_logic_pins(net) == 2); cell = lpm_cell_buf(); ref = edif_cellref_create(edf, cell); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); edif_add_to_joint(jnt, ref, 0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); edif_add_to_joint(jnt, ref, 1); break; case IVL_LO_BUFIF0: assert(ivl_logic_pins(net) == 3); cell = lpm_cell_bufif0(); ref = edif_cellref_create(edf, cell); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); edif_add_to_joint(jnt, ref, 0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); edif_add_to_joint(jnt, ref, 1); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2)); edif_add_to_joint(jnt, ref, 2); break; case IVL_LO_BUFIF1: assert(ivl_logic_pins(net) == 3); cell = lpm_cell_bufif1(); ref = edif_cellref_create(edf, cell); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); edif_add_to_joint(jnt, ref, 0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); edif_add_to_joint(jnt, ref, 1); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 2)); edif_add_to_joint(jnt, ref, 2); break; case IVL_LO_NOT: assert(ivl_logic_pins(net) == 2); cell = lpm_cell_inv(); ref = edif_cellref_create(edf, cell); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); edif_add_to_joint(jnt, ref, 0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 1)); edif_add_to_joint(jnt, ref, 1); break; case IVL_LO_OR: cell = lpm_cell_or(ivl_logic_pins(net)-1); hookup_logic_gate(net, cell); break; case IVL_LO_NOR: cell = lpm_cell_nor(ivl_logic_pins(net)-1); hookup_logic_gate(net, cell); break; case IVL_LO_AND: cell = lpm_cell_and(ivl_logic_pins(net)-1); hookup_logic_gate( net, cell); break; case IVL_LO_XOR: cell = lpm_cell_xor(ivl_logic_pins(net)-1); hookup_logic_gate( net, cell); break; default: fprintf(stderr, "UNSUPPORTED LOGIC TYPE: %u\n", ivl_logic_type(net)); break; } }
static void virtex_or_wide(ivl_net_logic_t net) { edif_cell_t cell_muxcy_l = xilinx_cell_muxcy_l(xlib); edif_cell_t cell_muxcy = xilinx_cell_muxcy(xlib); edif_cell_t cell_lut4 = xilinx_cell_lut4(xlib); edif_cellref_t true_out, false_out; edif_cellref_t lut, muxcy, muxcy_down=NULL; edif_joint_t jnt; unsigned idx, inputs, lut4_cnt; if (ivl_logic_type(net) == IVL_LO_OR) { true_out = edif_cellref_create(edf, cell_1); false_out = edif_cellref_create(edf, cell_0); } else { true_out = edif_cellref_create(edf, cell_0); false_out = edif_cellref_create(edf, cell_1); } inputs = ivl_logic_pins(net) - 1; lut4_cnt = (inputs-1)/4; for (idx = 0 ; idx < lut4_cnt ; idx += 1) { muxcy = edif_cellref_create(edf, cell_muxcy_l); lut = edif_cellref_create(edf, cell_lut4); edif_cellref_pstring(lut, "INIT", "0001"); jnt = edif_joint_create(edf); edif_add_to_joint(jnt, lut, LUT_O); edif_add_to_joint(jnt, muxcy, MUXCY_S); jnt = edif_joint_create(edf); edif_add_to_joint(jnt, true_out, 0); edif_add_to_joint(jnt, muxcy, MUXCY_DI); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+0)); edif_add_to_joint(jnt, lut, LUT_I0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+1)); edif_add_to_joint(jnt, lut, LUT_I1); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+2)); edif_add_to_joint(jnt, lut, LUT_I2); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, idx*4+1+3)); edif_add_to_joint(jnt, lut, LUT_I3); if (idx > 0) { jnt = edif_joint_create(edf); edif_add_to_joint(jnt, muxcy, MUXCY_CI); edif_add_to_joint(jnt, muxcy_down, MUXCY_O); } else { jnt = edif_joint_create(edf); edif_add_to_joint(jnt, muxcy, MUXCY_CI); edif_add_to_joint(jnt, false_out, 0); } muxcy_down = muxcy; } muxcy = edif_cellref_create(edf, cell_muxcy); jnt = edif_joint_create(edf); edif_add_to_joint(jnt, true_out, 0); edif_add_to_joint(jnt, muxcy, MUXCY_DI); jnt = edif_joint_create(edf); edif_add_to_joint(jnt, muxcy, MUXCY_CI); edif_add_to_joint(jnt, muxcy_down, MUXCY_O); switch (ivl_logic_pins(net) - 1 - lut4_cnt*4) { case 1: lut = edif_cellref_create(edf, xilinx_cell_inv(xlib)); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0)); edif_add_to_joint(jnt, lut, BUF_I); break; case 2: lut = edif_cellref_create(edf, xilinx_cell_lut2(xlib)); edif_cellref_pstring(lut, "INIT", "1"); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0)); edif_add_to_joint(jnt, lut, LUT_I0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1)); edif_add_to_joint(jnt, lut, LUT_I1); break; case 3: lut = edif_cellref_create(edf, xilinx_cell_lut3(xlib)); edif_cellref_pstring(lut, "INIT", "01"); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0)); edif_add_to_joint(jnt, lut, LUT_I0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1)); edif_add_to_joint(jnt, lut, LUT_I1); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2)); edif_add_to_joint(jnt, lut, LUT_I2); break; case 4: lut = edif_cellref_create(edf, cell_lut4); edif_cellref_pstring(lut, "INIT", "0001"); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+0)); edif_add_to_joint(jnt, lut, LUT_I0); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+1)); edif_add_to_joint(jnt, lut, LUT_I1); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+2)); edif_add_to_joint(jnt, lut, LUT_I2); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, lut4_cnt*4+1+3)); edif_add_to_joint(jnt, lut, LUT_I3); break; default: assert(0); } jnt = edif_joint_create(edf); edif_add_to_joint(jnt, lut, LUT_O); edif_add_to_joint(jnt, muxcy, MUXCY_S); jnt = edif_joint_of_nexus(edf, ivl_logic_pin(net, 0)); edif_add_to_joint(jnt, muxcy, MUXCY_O); }
static void edif_show_logic(ivl_net_logic_t net) { char jbuf[1024]; unsigned idx; edif_uref += 1; switch (ivl_logic_type(net)) { case IVL_LO_AND: assert(ivl_logic_pins(net) <= 10); assert(ivl_logic_pins(net) >= 3); fprintf(xnf, "(instance (rename U%u \"%s\")", edif_uref, ivl_logic_name(net)); fprintf(xnf, " (viewRef net" " (cellRef AND%u (libraryRef VIRTEX))))\n", ivl_logic_pins(net) - 1); sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { sprintf(jbuf, "(portRef I%u (instanceRef U%u))", idx-1, edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, idx), jbuf); } break; case IVL_LO_BUF: assert(ivl_logic_pins(net) == 2); fprintf(xnf, "(instance (rename U%u \"%s\")", edif_uref, ivl_logic_name(net)); fprintf(xnf, " (viewRef net" " (cellRef BUF (libraryRef VIRTEX))))\n"); sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf); sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf); break; case IVL_LO_BUFZ: { static int bufz_warned_once=0; if (!bufz_warned_once) { fprintf (stderr, "0:0: internal warning: BUFZ objects found " "in EDIF netlist.\n"); fprintf (stderr, "0:0: : I'll make BUFs for them.\n"); bufz_warned_once=1; } assert(ivl_logic_pins(net) == 2); fprintf(xnf, "(instance (rename U%u \"%s\")", edif_uref, ivl_logic_name(net)); fprintf(xnf, " (viewRef net" " (cellRef BUF (libraryRef VIRTEX))))\n"); sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf); sprintf(jbuf, "(portRef I (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 1), jbuf); } break; case IVL_LO_NOR: assert(ivl_logic_pins(net) <= 10); assert(ivl_logic_pins(net) >= 3); fprintf(xnf, "(instance (rename U%u \"%s\")", edif_uref, ivl_logic_name(net)); fprintf(xnf, " (viewRef net" " (cellRef NOR%u (libraryRef VIRTEX))))\n", ivl_logic_pins(net) - 1); sprintf(jbuf, "(portRef O (instanceRef U%u))", edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, 0), jbuf); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { sprintf(jbuf, "(portRef I%u (instanceRef U%u))", idx-1, edif_uref); edif_set_nexus_joint(ivl_logic_pin(net, idx), jbuf); } break; default: fprintf(stderr, "UNSUPPORT LOGIC TYPE: %u\n", ivl_logic_type(net)); } }
static void generic_show_logic(ivl_net_logic_t net) { char name[1024]; ivl_nexus_t nex; unsigned idx; xnf_mangle_logic_name(net, name, sizeof name); switch (ivl_logic_type(net)) { case IVL_LO_AND: fprintf(xnf, "SYM, %s, AND, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_BUF: assert(ivl_logic_pins(net) == 2); fprintf(xnf, "SYM, %s, BUF, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); nex = ivl_logic_pin(net, 1); xnf_draw_pin(nex, "I", 'I'); fprintf(xnf, "END\n"); break; case IVL_LO_NAND: fprintf(xnf, "SYM, %s, NAND, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_NOR: fprintf(xnf, "SYM, %s, NOR, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_NOT: assert(ivl_logic_pins(net) == 2); fprintf(xnf, "SYM, %s, INV, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); nex = ivl_logic_pin(net, 1); xnf_draw_pin(nex, "I", 'I'); fprintf(xnf, "END\n"); break; case IVL_LO_OR: fprintf(xnf, "SYM, %s, OR, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_XOR: fprintf(xnf, "SYM, %s, XOR, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_XNOR: fprintf(xnf, "SYM, %s, XNOR, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); for (idx = 1 ; idx < ivl_logic_pins(net) ; idx += 1) { char ipin[32]; nex = ivl_logic_pin(net, idx); sprintf(ipin, "I%u", idx-1); xnf_draw_pin(nex, ipin, 'I'); } fprintf(xnf, "END\n"); break; case IVL_LO_BUFIF0: fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); nex = ivl_logic_pin(net, 1); xnf_draw_pin(nex, "I", 'I'); nex = ivl_logic_pin(net, 2); xnf_draw_pin(nex, "~T", 'I'); fprintf(xnf, "END\n"); break; case IVL_LO_BUFIF1: fprintf(xnf, "SYM, %s, TBUF, LIBVER=2.0.0\n", name); nex = ivl_logic_pin(net, 0); xnf_draw_pin(nex, "O", 'O'); nex = ivl_logic_pin(net, 1); xnf_draw_pin(nex, "I", 'I'); nex = ivl_logic_pin(net, 2); xnf_draw_pin(nex, "T", 'I'); fprintf(xnf, "END\n"); break; default: fprintf(stderr, "fpga.tgt: unknown logic type %u\n", ivl_logic_type(net)); break; } }
static void draw_logic_in_scope(ivl_net_logic_t lptr) { unsigned pdx; const char*ltype = "?"; const char*lcasc = 0; char identity_val = '0'; int need_delay_flag = ivl_logic_delay(lptr,0)? 1 : 0; unsigned vector_width = width_of_nexus(ivl_logic_pin(lptr, 0)); ivl_drive_t str0, str1; int level; int ninp = ivl_logic_pins(lptr) - 1; typedef const char*const_charp; const_charp*input_strings = calloc(ninp, sizeof(const_charp)); for (pdx = 0 ; pdx < ninp ; pdx += 1) { ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1); if (nex == 0) { /* Only UDPs can have unconnected inputs. */ assert(ivl_logic_type(lptr) == IVL_LO_UDP); input_strings[pdx] = 0; } else { input_strings[pdx] = draw_net_input(nex); } } switch (ivl_logic_type(lptr)) { case IVL_LO_UDP: free(input_strings); draw_udp_in_scope(lptr); return; case IVL_LO_BUFZ: { /* Draw bufz objects, but only if the gate cannot be elided. If I can elide it, then the draw_nex_input will take care of it for me. */ ivl_nexus_ptr_t nptr = ivl_logic_pin_ptr(lptr,0); ltype = "BUFZ"; if (can_elide_bufz(lptr, nptr)) return; break; } case IVL_LO_PULLDOWN: case IVL_LO_PULLUP: /* Skip pullup and pulldown objects. Things that have pull objects as inputs will instead generate the appropriate C<?> symbol. */ free(input_strings); return; case IVL_LO_AND: ltype = "AND"; identity_val = '1'; break; case IVL_LO_BUF: ltype = "BUF"; break; case IVL_LO_BUFIF0: ltype = "BUFIF0"; break; case IVL_LO_BUFIF1: ltype = "BUFIF1"; break; case IVL_LO_NAND: ltype = "NAND"; lcasc = "AND"; identity_val = '1'; break; case IVL_LO_NOR: ltype = "NOR"; lcasc = "OR"; break; case IVL_LO_NOT: ltype = "NOT"; break; case IVL_LO_OR: ltype = "OR"; break; case IVL_LO_XNOR: ltype = "XNOR"; lcasc = "XOR"; break; case IVL_LO_XOR: ltype = "XOR"; break; case IVL_LO_CMOS: ltype = "CMOS"; break; case IVL_LO_PMOS: ltype = "PMOS"; break; case IVL_LO_NMOS: ltype = "NMOS"; break; case IVL_LO_RCMOS: ltype = "RCMOS"; break; case IVL_LO_RPMOS: ltype = "RPMOS"; break; case IVL_LO_RNMOS: ltype = "RNMOS"; break; case IVL_LO_NOTIF0: ltype = "NOTIF0"; break; case IVL_LO_NOTIF1: ltype = "NOTIF1"; break; default: fprintf(stderr, "vvp.tgt: error: Unhandled logic type: %u\n", ivl_logic_type(lptr)); ltype = "?"; break; } { ivl_nexus_t nex = ivl_logic_pin(lptr, 0); ivl_nexus_ptr_t nptr = 0; unsigned idx; for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) { nptr = ivl_nexus_ptr(nex,idx); if (ivl_nexus_ptr_log(nptr) != lptr) continue; if (ivl_nexus_ptr_pin(nptr) != 0) continue; break; } str0 = ivl_nexus_ptr_drive0(nptr); str1 = ivl_nexus_ptr_drive1(nptr); } if (!lcasc) lcasc = ltype; /* Get all the input label that I will use for parameters to the functor that I create later. */ ninp = ivl_logic_pins(lptr) - 1; input_strings = calloc(ninp, sizeof(char*)); for (pdx = 0 ; pdx < ninp ; pdx += 1) input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1)); level = 0; ninp = ivl_logic_pins(lptr) - 1; while (ninp) { int inst; for (inst = 0; inst < ninp; inst += 4) { if (ninp > 4) fprintf(vvp_out, "L_%p/%d/%d .functor %s %u", lptr, level, inst, lcasc, vector_width); else { fprintf(vvp_out, "L_%p%s .functor %s %u", lptr, need_delay_flag? "/d" : "", ltype, vector_width); if (str0 != IVL_DR_STRONG || str1 != IVL_DR_STRONG) fprintf(vvp_out, " [%u %u]", str0, str1); } for (pdx = inst; pdx < ninp && pdx < inst+4 ; pdx += 1) { if (level) { fprintf(vvp_out, ", L_%p/%d/%d", lptr, level - 1, pdx*4); } else { fprintf(vvp_out, ", %s", input_strings[pdx]); } } for ( ; pdx < inst+4 ; pdx += 1) { unsigned wdx; fprintf(vvp_out, ", C4<"); for (wdx = 0 ; wdx < vector_width ; wdx += 1) fprintf(vvp_out, "%c", identity_val); fprintf(vvp_out, ">"); } fprintf(vvp_out, ";\n"); } if (ninp > 4) ninp = (ninp+3) / 4; else ninp = 0; level += 1; } /* Free the array of char*. The strings themselves are persistent, held by the ivl_nexus_t objects. */ free(input_strings); /* If there are delays, then draw the delay functor to carry that delay. This is the final output. */ if (need_delay_flag) { ivl_expr_t rise_exp = ivl_logic_delay(lptr,0); ivl_expr_t fall_exp = ivl_logic_delay(lptr,1); ivl_expr_t decay_exp = ivl_logic_delay(lptr,2); if (number_is_immediate(rise_exp,64,0) && number_is_immediate(fall_exp,64,0) && number_is_immediate(decay_exp,64,0)) { fprintf(vvp_out, "L_%p .delay (%lu,%lu,%lu) L_%p/d;\n", lptr, get_number_immediate(rise_exp), get_number_immediate(rise_exp), get_number_immediate(rise_exp), lptr); } else { ivl_signal_t sig; assert(ivl_expr_type(rise_exp) == IVL_EX_SIGNAL); assert(ivl_expr_type(fall_exp) == IVL_EX_SIGNAL); assert(ivl_expr_type(decay_exp) == IVL_EX_SIGNAL); fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr); sig = ivl_expr_signal(rise_exp); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(fall_exp); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0", sig); sig = ivl_expr_signal(decay_exp); assert(ivl_signal_dimensions(sig) == 0); fprintf(vvp_out, ", v%p_0;\n", sig); } } }
/* * All logic gates have inputs and outputs that match exactly in * width. For example, and AND gate with 4 bit inputs generates a 4 * bit output, and all the inputs are 4 bits. */ static void show_logic(ivl_net_logic_t net) { unsigned npins, idx; const char*name = ivl_logic_basename(net); ivl_drive_t drive0 = ivl_logic_drive0(net); ivl_drive_t drive1 = ivl_logic_drive1(net); switch (ivl_logic_type(net)) { case IVL_LO_AND: fprintf(out, " and %s", name); break; case IVL_LO_BUF: fprintf(out, " buf %s", name); break; case IVL_LO_BUFIF0: fprintf(out, " bufif0 %s", name); break; case IVL_LO_BUFIF1: fprintf(out, " bufif1 %s", name); break; case IVL_LO_BUFT: fprintf(out, " buft %s", name); break; case IVL_LO_BUFZ: fprintf(out, " bufz %s", name); break; case IVL_LO_CMOS: fprintf(out, " cmos %s", name); break; case IVL_LO_NAND: fprintf(out, " nand %s", name); break; case IVL_LO_NMOS: fprintf(out, " nmos %s", name); break; case IVL_LO_NOR: fprintf(out, " nor %s", name); break; case IVL_LO_NOT: fprintf(out, " not %s", name); break; case IVL_LO_NOTIF0: fprintf(out, " notif0 %s", name); break; case IVL_LO_NOTIF1: fprintf(out, " notif1 %s", name); break; case IVL_LO_OR: fprintf(out, " or %s", name); break; case IVL_LO_PMOS: fprintf(out, " pmos %s", name); break; case IVL_LO_PULLDOWN: fprintf(out, " pulldown %s", name); break; case IVL_LO_PULLUP: fprintf(out, " pullup %s", name); break; case IVL_LO_RCMOS: fprintf(out, " rcmos %s", name); break; case IVL_LO_RNMOS: fprintf(out, " rnmos %s", name); break; case IVL_LO_RPMOS: fprintf(out, " rpmos %s", name); break; case IVL_LO_XNOR: fprintf(out, " xnor %s", name); break; case IVL_LO_XOR: fprintf(out, " xor %s", name); break; case IVL_LO_UDP: fprintf(out, " primitive<%s> %s", ivl_udp_name(ivl_logic_udp(net)), name); break; default: fprintf(out, " unsupported gate<type=%d> %s", ivl_logic_type(net), name); break; } fprintf(out, " <width=%u>\n", ivl_logic_width(net)); fprintf(out, " <Delays...>\n"); if (ivl_logic_delay(net,0)) { test_expr_is_delay(ivl_logic_delay(net,0)); show_expression(ivl_logic_delay(net,0), 6); } if (ivl_logic_delay(net,1)) { test_expr_is_delay(ivl_logic_delay(net,1)); show_expression(ivl_logic_delay(net,1), 6); } if (ivl_logic_delay(net,2)) { test_expr_is_delay(ivl_logic_delay(net,2)); show_expression(ivl_logic_delay(net,2), 6); } npins = ivl_logic_pins(net); /* Show the pins of the gate. Pin-0 is always the output, and the remaining pins are the inputs. Inputs may be unconnected, but if connected the nexus width must exactly match the gate width. */ for (idx = 0 ; idx < npins ; idx += 1) { ivl_nexus_t nex = ivl_logic_pin(net, idx); fprintf(out, " %d: %p", idx, nex); if (idx == 0) fprintf(out, " <drive0/1 = %u/%u>", drive0, drive1); fprintf(out, "\n"); if (nex == 0) { if (idx == 0) { fprintf(out, " 0: ERROR: Pin 0 must not " "be unconnected\n"); stub_errors += 1; } continue; } if (ivl_logic_width(net) != width_of_nexus(nex)) { fprintf(out, " %d: ERROR: Nexus width is %u\n", idx, width_of_nexus(nex)); stub_errors += 1; } } /* If this is an instance of a UDP, then check that the instantiation is consistent with the definition. */ if (ivl_logic_type(net) == IVL_LO_UDP) { ivl_udp_t udp = ivl_logic_udp(net); if (npins != 1+ivl_udp_nin(udp)) { fprintf(out, " ERROR: UDP %s expects %u inputs\n", ivl_udp_name(udp), ivl_udp_nin(udp)); stub_errors += 1; } /* Add a reference to this udp definition. */ reference_udp_definition(udp); } npins = ivl_logic_attr_cnt(net); for (idx = 0 ; idx < npins ; idx += 1) { ivl_attribute_t cur = ivl_logic_attr_val(net,idx); switch (cur->type) { case IVL_ATT_VOID: fprintf(out, " %s\n", cur->key); break; case IVL_ATT_NUM: fprintf(out, " %s = %ld\n", cur->key, cur->val.num); break; case IVL_ATT_STR: fprintf(out, " %s = %s\n", cur->key, cur->val.str); break; } } }