static void emit_stmt_fork_named(ivl_scope_t scope, ivl_statement_t stmt) { ivl_scope_t my_scope = ivl_stmt_block_scope(stmt); fprintf(vlog_out, "%*cfork: ", get_indent(), ' '); emit_id(ivl_scope_basename(my_scope)); emit_stmt_file_line(stmt); fprintf(vlog_out, "\n"); emit_stmt_block_body(scope, stmt); fprintf(vlog_out, "%*cjoin /* %s */\n", get_indent(), ' ', ivl_scope_basename(my_scope)); }
static void emit_expr_scope_piece(ivl_scope_t scope) { ivl_scope_t parent = ivl_scope_parent(scope); /* If this scope has a parent then emit it first. */ if (parent) { emit_expr_scope_piece(parent); fprintf(vlog_out, "."); } emit_id(ivl_scope_basename(scope)); }
/* * This routine emits the appropriate string to call the call_scope from the * given scope. If the module scopes for the two match then just return the * base name of the call_scope. If the module scopes are different, but the * call_scope begins with the entire module scope of scope then we can trim * the top off the call_scope (it is a sub-scope of the module that contains * scope). Otherwise we need to print the entire path of call_scope. */ void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope) { ivl_scope_t mod_scope = get_module_scope(scope); ivl_scope_t call_mod_scope = get_module_scope(call_scope); if (mod_scope == call_mod_scope) { emit_id(ivl_scope_basename(call_scope)); } else { emit_scope_path_piece(mod_scope, call_scope); } }
static void emit_scope_path_piece(ivl_scope_t scope, ivl_scope_t call_scope) { ivl_scope_t parent = ivl_scope_parent(call_scope); /* If we are not at the top of the scope (parent != 0) and the two * scopes do not match then print the parent scope. */ if ((parent != 0) && (scope != parent)) { emit_scope_path_piece(scope, parent); fprintf(vlog_out, "."); } /* Print the base scope. */ emit_id(ivl_scope_basename(call_scope)); }
static void lpm_show_header(ivl_design_t des) { unsigned idx; ivl_scope_t root = ivl_design_root(des); unsigned sig_cnt = ivl_scope_sigs(root); unsigned nports = 0, pidx; /* Count the ports I'm going to use. */ for (idx = 0 ; idx < sig_cnt ; idx += 1) { ivl_signal_t sig = ivl_scope_sig(root, idx); if (ivl_signal_port(sig) == IVL_SIP_NONE) continue; if (ivl_signal_attr(sig, "PAD") != 0) continue; nports += ivl_signal_pins(sig); } /* Create the base edf object. */ edf = edif_create(ivl_scope_basename(root), nports); pidx = 0; for (idx = 0 ; idx < sig_cnt ; idx += 1) { edif_joint_t jnt; ivl_signal_t sig = ivl_scope_sig(root, idx); if (ivl_signal_port(sig) == IVL_SIP_NONE) continue; if (ivl_signal_attr(sig, "PAD") != 0) continue; if (ivl_signal_pins(sig) == 1) { edif_portconfig(edf, pidx, ivl_signal_basename(sig), ivl_signal_port(sig)); assert(ivl_signal_pins(sig) == 1); jnt = edif_joint_of_nexus(edf, ivl_signal_pin(sig, 0)); edif_port_to_joint(jnt, edf, pidx); } else { const char*name = ivl_signal_basename(sig); ivl_signal_port_t dir = ivl_signal_port(sig); char buf[128]; unsigned bit; for (bit = 0 ; bit < ivl_signal_pins(sig) ; bit += 1) { const char*tmp; sprintf(buf, "%s[%u]", name, bit); tmp = strdup(buf); edif_portconfig(edf, pidx+bit, tmp, dir); jnt = edif_joint_of_nexus(edf,ivl_signal_pin(sig,bit)); edif_port_to_joint(jnt, edf, pidx+bit); } } pidx += ivl_signal_pins(sig); } assert(pidx == nports); xlib = edif_xlibrary_create(edf, "LPM_LIBRARY"); }
// 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; }
int draw_scope(ivl_scope_t net, ivl_scope_t parent) { unsigned idx; const char *type; const char*prefix = ivl_scope_is_auto(net) ? "auto" : ""; switch (ivl_scope_type(net)) { case IVL_SCT_MODULE: type = "module"; break; case IVL_SCT_FUNCTION: type = "function"; break; case IVL_SCT_TASK: type = "task"; break; case IVL_SCT_BEGIN: type = "begin"; break; case IVL_SCT_FORK: type = "fork"; break; case IVL_SCT_GENERATE: type = "generate"; break; default: type = "?"; assert(0); } fprintf(vvp_out, "S_%p .scope %s%s, \"%s\" \"%s\" %d %d", net, prefix, type, vvp_mangle_name(ivl_scope_basename(net)), ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)), ivl_scope_lineno(net)); if (parent) { fprintf(vvp_out, ", %d %d, S_%p;\n", ivl_file_table_index(ivl_scope_def_file(net)), ivl_scope_def_lineno(net), parent); } else { fprintf(vvp_out, ";\n"); } fprintf(vvp_out, " .timescale %d %d;\n", ivl_scope_time_units(net), ivl_scope_time_precision(net)); for (idx = 0 ; idx < ivl_scope_params(net) ; idx += 1) { ivl_parameter_t par = ivl_scope_param(net, idx); ivl_expr_t pex = ivl_parameter_expr(par); switch (ivl_expr_type(pex)) { case IVL_EX_STRING: fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d, \"%s\";\n", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), ivl_expr_string(pex)); break; case IVL_EX_NUMBER: fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d, %sC4<", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), ivl_expr_signed(pex)? "+":""); { const char*bits = ivl_expr_bits(pex); unsigned nbits = ivl_expr_width(pex); unsigned bb; for (bb = 0 ; bb < nbits; bb += 1) fprintf(vvp_out, "%c", bits[nbits-bb-1]); } fprintf(vvp_out, ">;\n"); break; case IVL_EX_REALNUM: fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%g\n", par, ivl_parameter_basename(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), draw_Cr_to_string(ivl_expr_dvalue(pex)), ivl_expr_dvalue(pex)); break; default: fprintf(vvp_out, "; parameter type %d unsupported\n", ivl_expr_type(pex)); break; } } /* Scan the scope for logic devices. For each device, draw out a functor that connects pin 0 to the output, and the remaining pins to inputs. */ for (idx = 0 ; idx < ivl_scope_logs(net) ; idx += 1) { ivl_net_logic_t lptr = ivl_scope_log(net, idx); draw_logic_in_scope(lptr); } /* Scan the signals (reg and net) and draw the appropriate statements to make the signal function. */ for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1) { ivl_signal_t sig = ivl_scope_sig(net, idx); switch (ivl_signal_type(sig)) { case IVL_SIT_REG: draw_reg_in_scope(sig); break; default: draw_net_in_scope(sig); break; } } for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1) { ivl_event_t event = ivl_scope_event(net, idx); draw_event_in_scope(event); } for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) { ivl_lpm_t lpm = ivl_scope_lpm(net, idx); draw_lpm_in_scope(lpm); } for (idx = 0 ; idx < ivl_scope_switches(net) ; idx += 1) { ivl_switch_t sw = ivl_scope_switch(net, idx); draw_switch_in_scope(sw); } if (ivl_scope_type(net) == IVL_SCT_TASK) draw_task_definition(net); if (ivl_scope_type(net) == IVL_SCT_FUNCTION) draw_func_definition(net); ivl_scope_children(net, (ivl_scope_f*) draw_scope, net); return 0; }