/* aset is zero if there's no aset input at all or (there's a set input and values !=NULL and this bit of aset_value sets to 0). */ static int aset_zero (ivl_lpm_t ff, int idx) { return (NULL == ivl_lpm_async_set (ff)) || (ivl_lpm_async_set (ff) && (ivl_lpm_aset_value (ff) != NULL) && (ivl_expr_bits (ivl_lpm_aset_value (ff))[idx] == '0')); }
/* aclr is zero if there's no aclr input or (there's a set input and (aset_value ==NULL or aset_value bit of 1)) */ static int aclr_zero (ivl_lpm_t ff, int idx) { return (NULL == ivl_lpm_async_clr (ff)) || (ivl_lpm_async_set (ff) && ((ivl_lpm_aset_value (ff) == NULL) || /*does this work? */ (ivl_expr_bits (ivl_lpm_aset_value (ff))[idx] == '1'))); }
static void lpm_show_dff(ivl_lpm_t net) { char name[64]; edif_cell_t cell; edif_cellref_t ref; edif_joint_t jnt; unsigned idx; unsigned pin, wid = ivl_lpm_width(net); sprintf(name, "fd%s%s%s%s%s%u", ivl_lpm_enable(net)? "ce" : "", ivl_lpm_async_clr(net)? "cl" : "", ivl_lpm_sync_clr(net)? "sc" : "", ivl_lpm_async_set(net)? "se" : "", ivl_lpm_sync_set(net)? "ss" : "", wid); cell = edif_xlibrary_findcell(xlib, name); if (cell == 0) { unsigned nports = 2 * wid + 1; pin = 0; if (ivl_lpm_enable(net)) nports += 1; if (ivl_lpm_async_clr(net)) nports += 1; if (ivl_lpm_sync_clr(net)) nports += 1; if (ivl_lpm_async_set(net)) nports += 1; if (ivl_lpm_sync_set(net)) nports += 1; cell = edif_xcell_create(xlib, strdup(name), nports); edif_cell_pstring(cell, "LPM_Type", "LPM_FF"); edif_cell_pinteger(cell, "LPM_Width", wid); for (idx = 0 ; idx < wid ; idx += 1) { sprintf(name, "Q%u", idx); edif_cell_portconfig(cell, idx*2+0, strdup(name), IVL_SIP_OUTPUT); sprintf(name, "Data%u", idx); edif_cell_portconfig(cell, idx*2+1, strdup(name), IVL_SIP_INPUT); } pin = wid*2; if (ivl_lpm_enable(net)) { edif_cell_portconfig(cell, pin, "Enable", IVL_SIP_INPUT); pin += 1; } if (ivl_lpm_async_clr(net)) { edif_cell_portconfig(cell, pin, "Aclr", IVL_SIP_INPUT); pin += 1; } if (ivl_lpm_sync_clr(net)) { edif_cell_portconfig(cell, pin, "Sclr", IVL_SIP_INPUT); pin += 1; } if (ivl_lpm_async_set(net)) { edif_cell_portconfig(cell, pin, "Aset", IVL_SIP_INPUT); pin += 1; } if (ivl_lpm_sync_set(net)) { edif_cell_portconfig(cell, pin, "Sset", IVL_SIP_INPUT); pin += 1; } edif_cell_portconfig(cell, pin, "Clock", IVL_SIP_INPUT); pin += 1; assert(pin == nports); } ref = edif_cellref_create(edf, cell); pin = edif_cell_port_byname(cell, "Clock"); jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net)); edif_add_to_joint(jnt, ref, pin); if (ivl_lpm_enable(net)) { pin = edif_cell_port_byname(cell, "Enable"); jnt = edif_joint_of_nexus(edf, ivl_lpm_enable(net)); edif_add_to_joint(jnt, ref, pin); } if (ivl_lpm_async_clr(net)) { pin = edif_cell_port_byname(cell, "Aclr"); jnt = edif_joint_of_nexus(edf, ivl_lpm_async_clr(net)); edif_add_to_joint(jnt, ref, pin); } if (ivl_lpm_sync_clr(net)) { pin = edif_cell_port_byname(cell, "Sclr"); jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_clr(net)); edif_add_to_joint(jnt, ref, pin); } if (ivl_lpm_async_set(net)) { pin = edif_cell_port_byname(cell, "Aset"); jnt = edif_joint_of_nexus(edf, ivl_lpm_async_set(net)); edif_add_to_joint(jnt, ref, pin); } if (ivl_lpm_sync_set(net)) { ivl_expr_t svalue = ivl_lpm_sset_value(net); pin = edif_cell_port_byname(cell, "Sset"); jnt = edif_joint_of_nexus(edf, ivl_lpm_sync_set(net)); edif_add_to_joint(jnt, ref, pin); edif_cellref_pinteger(ref, "LPM_Svalue", ivl_expr_uvalue(svalue)); } for (idx = 0 ; idx < wid ; idx += 1) { sprintf(name, "Q%u", idx); pin = edif_cell_port_byname(cell, name); jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); edif_add_to_joint(jnt, ref, pin); sprintf(name, "Data%u", idx); pin = edif_cell_port_byname(cell, name); jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx)); edif_add_to_joint(jnt, ref, pin); } }
// 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; }
void virtex_generic_dff(ivl_lpm_t net) { unsigned idx; ivl_nexus_t aclr = ivl_lpm_async_clr(net); ivl_nexus_t aset = ivl_lpm_async_set(net); ivl_nexus_t sclr = ivl_lpm_sync_clr(net); ivl_nexus_t sset = ivl_lpm_sync_set(net); const char*abits = 0; if (aset) { ivl_expr_t avalue = ivl_lpm_aset_value(net); assert(avalue); abits = ivl_expr_bits(avalue); assert(abits); } /* XXXX Can't handle both synchronous and asynchronous clear. */ assert( ! (aclr && sclr) ); /* XXXX Can't handle synchronous set at all. */ assert( ! sset ); for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) { edif_cellref_t obj; ivl_nexus_t nex; edif_joint_t jnt; /* If there is a preset, then select an FDCPE instead of an FDCE device. */ if (aset && (abits[idx] == '1')) { obj = edif_cellref_create(edf, xilinx_cell_fdcpe(xlib)); } else if (aclr) { obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib)); } else if (sclr) { obj = edif_cellref_create(edf, xilinx_cell_fdre(xlib)); } else { obj = edif_cellref_create(edf, xilinx_cell_fdce(xlib)); } jnt = edif_joint_of_nexus(edf, ivl_lpm_q(net, idx)); edif_add_to_joint(jnt, obj, FDCE_Q); jnt = edif_joint_of_nexus(edf, ivl_lpm_data(net, idx)); edif_add_to_joint(jnt, obj, FDCE_D); jnt = edif_joint_of_nexus(edf, ivl_lpm_clk(net)); edif_add_to_joint(jnt, obj, FDCE_C); if ( (nex = ivl_lpm_enable(net)) ) { jnt = edif_joint_of_nexus(edf, nex); edif_add_to_joint(jnt, obj, FDCE_CE); } if (aclr) { jnt = edif_joint_of_nexus(edf, aclr); edif_add_to_joint(jnt, obj, FDCE_CLR); } else if (sclr) { jnt = edif_joint_of_nexus(edf, sclr); edif_add_to_joint(jnt, obj, FDCE_CLR); } if (aset) { if (abits[idx] == '1') { jnt = edif_joint_of_nexus(edf, aset); edif_add_to_joint(jnt, obj, FDCE_PRE); } else { assert(aclr == 0); jnt = edif_joint_of_nexus(edf, aset); edif_add_to_joint(jnt, obj, FDCE_CLR); } } } }
static void edif_show_generic_dff(ivl_lpm_t net) { ivl_nexus_t nex; char jbuf[1024]; unsigned idx; ivl_nexus_t aclr = ivl_lpm_async_clr(net); ivl_nexus_t aset = ivl_lpm_async_set(net); ivl_expr_t avalue = 0; const char*abits = 0; const char*fdcell = "FDCE"; if (aset != 0) { fdcell = "FDCPE"; avalue = ivl_lpm_aset_value(net); assert(avalue); abits = ivl_expr_bits(avalue); assert(abits); } for (idx = 0 ; idx < ivl_lpm_width(net) ; idx += 1) { edif_uref += 1; fprintf(xnf, "(instance (rename U%u \"%s.%s[%u]\")", edif_uref, ivl_scope_name(ivl_lpm_scope(net)), ivl_lpm_basename(net), idx); fprintf(xnf, " (viewRef net" " (cellRef %s (libraryRef VIRTEX))))\n", fdcell); nex = ivl_lpm_q(net, idx); sprintf(jbuf, "(portRef Q (instanceRef U%u))", edif_uref); edif_set_nexus_joint(nex, jbuf); nex = ivl_lpm_data(net, idx); sprintf(jbuf, "(portRef D (instanceRef U%u))", edif_uref); edif_set_nexus_joint(nex, jbuf); nex = ivl_lpm_clk(net); sprintf(jbuf, "(portRef C (instanceRef U%u))", edif_uref); edif_set_nexus_joint(nex, jbuf); if ((nex = ivl_lpm_enable(net))) { sprintf(jbuf, "(portRef CE (instanceRef U%u))", edif_uref); edif_set_nexus_joint(nex, jbuf); } if (aclr) { sprintf(jbuf, "(portRef CLR (instanceRef U%u))", edif_uref); edif_set_nexus_joint(aclr, jbuf); } if (aset) { if (abits[idx] == '1') { sprintf(jbuf, "(portRef PRE (instanceRef U%u))", edif_uref); edif_set_nexus_joint(aset, jbuf); } else { assert(aclr == 0); sprintf(jbuf, "(portRef CLR (instanceRef U%u))", edif_uref); edif_set_nexus_joint(aset, jbuf); } } } }