void emit_process(ivl_scope_t scope, ivl_process_t proc) { ivl_statement_t stmt; fprintf(vlog_out, "\n%*c", get_indent(), ' '); switch (ivl_process_type(proc)) { case IVL_PR_INITIAL: fprintf(vlog_out, "initial"); break; case IVL_PR_ALWAYS: fprintf(vlog_out, "always"); break; default: fprintf(vlog_out, "<unknown>"); fprintf(stderr, "%s:%u: vlog95 error: Unknown process type (%d).\n", ivl_process_file(proc), ivl_process_lineno(proc), (int)ivl_process_type(proc)); vlog_errors+= 1; break; } if (emit_file_line) { fprintf(vlog_out, " /* %s:%u */", ivl_process_file(proc), ivl_process_lineno(proc)); } stmt = ivl_process_stmt(proc); if (ivl_statement_type(stmt) == IVL_ST_NOOP) { fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' '); } else { single_indent = 1; emit_stmt(scope, stmt); } }
/* * Processes are all collected by ivl and I draw them here in the root * scope. This way, I don't need to do anything about scope * references. */ static int show_process(ivl_process_t net, void*x) { switch (ivl_process_type(net)) { case IVL_PR_INITIAL: fprintf(out, " initial\n"); break; case IVL_PR_ALWAYS: fprintf(out, " always\n"); break; case IVL_PR_FINAL: fprintf(out, " final\n"); break; } show_statement(ivl_process_stmt(net), 8); return 0; }
static int show_process(ivl_process_t net, void*x) { unsigned idx; switch (ivl_process_type(net)) { case IVL_PR_INITIAL: if (ivl_process_analog(net)) fprintf(out, "analog initial\n"); else fprintf(out, "initial\n"); break; case IVL_PR_ALWAYS: if (ivl_process_analog(net)) fprintf(out, "analog\n"); else fprintf(out, "always\n"); break; } for (idx = 0 ; idx < ivl_process_attr_cnt(net) ; idx += 1) { ivl_attribute_t attr = ivl_process_attr_val(net, idx); switch (attr->type) { case IVL_ATT_VOID: fprintf(out, " (* %s *)\n", attr->key); break; case IVL_ATT_STR: fprintf(out, " (* %s = \"%s\" *)\n", attr->key, attr->val.str); break; case IVL_ATT_NUM: fprintf(out, " (* %s = %ld *)\n", attr->key, attr->val.num); break; } } show_statement(ivl_process_stmt(net), 4); return 0; }
int draw_process(ivl_process_t net, void*x) { int rc = 0; unsigned idx; ivl_scope_t scope = ivl_process_scope(net); ivl_statement_t stmt = ivl_process_stmt(net); int push_flag = 0; for (idx = 0 ; idx < ivl_process_attr_cnt(net) ; idx += 1) { ivl_attribute_t attr = ivl_process_attr_val(net, idx); if (strcmp(attr->key, "_ivl_schedule_push") == 0) { push_flag = 1; } else if (strcmp(attr->key, "ivl_combinational") == 0) { push_flag = 1; } } local_count = 0; fprintf(vvp_out, " .scope S_%p;\n", scope); /* Generate the entry label. Just give the thread a number so that we ar certain the label is unique. */ fprintf(vvp_out, "T_%d ;\n", thread_count); clear_expression_lookaside(); /* Draw the contents of the thread. */ rc += show_statement(stmt, scope); /* Terminate the thread with either an %end instruction (initial statements) or a %jmp back to the beginning of the thread. */ switch (ivl_process_type(net)) { case IVL_PR_INITIAL: fprintf(vvp_out, " %%end;\n"); break; case IVL_PR_ALWAYS: fprintf(vvp_out, " %%jmp T_%d;\n", thread_count); break; } /* Now write out the .thread directive that tells vvp where the thread starts. */ if (push_flag) { fprintf(vvp_out, " .thread T_%d, $push;\n", thread_count); } else { fprintf(vvp_out, " .thread T_%d;\n", thread_count); } thread_count += 1; return rc; }