vlog95: Add support for escaped ids and most module ports

This patch adds support for emitting escaped identifiers and adds
code to correctly emit most module port expressions/definitions.
There are some minor code optimizations/cleanup included as well.
This commit is contained in:
Cary R 2011-03-13 16:13:39 -07:00 committed by Stephen Williams
parent 1fbe777c81
commit e375b26f78
9 changed files with 423 additions and 239 deletions

View File

@ -65,7 +65,7 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
if (first) first = 0;
else fprintf(vlog_out, " or ");
emit_scope_module_path(scope, ev_scope);
fprintf(vlog_out, "%s", ivl_event_basename(event));
emit_id(ivl_event_basename(event));
}
}
}

View File

@ -73,7 +73,7 @@ static void emit_expr_array(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(expr);
emit_scope_call_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
emit_id(ivl_signal_basename(sig));
}
static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
@ -220,12 +220,23 @@ static void emit_expr_event(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
assert(! ivl_event_npos(event));
assert(! ivl_event_nneg(event));
emit_scope_call_path(scope, ev_scope);
fprintf(vlog_out, "%s", ivl_event_basename(event));
emit_id(ivl_event_basename(event));
}
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));
}
static void emit_expr_scope(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
fprintf(vlog_out, "%s", ivl_scope_name(ivl_expr_scope(expr)));
emit_expr_scope_piece(ivl_expr_scope(expr));
}
static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr)
@ -258,7 +269,7 @@ static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr)
break;
}
}
fprintf(vlog_out, "%s", ivl_parameter_basename(par));
emit_id(ivl_parameter_basename(par));
return 1;
}
}
@ -418,11 +429,10 @@ static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
/*
* This routine is used to emit both system and user functions.
*/
static void emit_expr_func(ivl_scope_t scope, ivl_expr_t expr, const char* name)
static void emit_expr_func(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
unsigned count = ivl_expr_parms(expr);
fprintf(vlog_out, "%s", name);
if (count != 0) {
if (count) {
unsigned idx;
fprintf(vlog_out, "(");
count -= 1;
@ -435,16 +445,11 @@ static void emit_expr_func(ivl_scope_t scope, ivl_expr_t expr, const char* name)
}
}
static void emit_expr_sfunc(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
emit_expr_func(scope, expr, ivl_expr_name(expr));
}
static void emit_expr_signal(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_signal_t sig = ivl_expr_signal(expr);
emit_scope_call_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
emit_id(ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig)) {
int lsb = ivl_signal_array_base(sig);
int msb = lsb + ivl_signal_array_count(sig);
@ -465,13 +470,6 @@ static void emit_expr_ternary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
fprintf(vlog_out, ")");
}
static void emit_expr_ufunc(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
ivl_scope_t ufunc_def = ivl_expr_def(expr);
emit_scope_module_path(scope, ufunc_def);
emit_expr_func(scope, expr, ivl_scope_tname(ufunc_def));
}
static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
{
char *oper = "invalid";
@ -551,7 +549,8 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
emit_expr_select(scope, expr, wid);
break;
case IVL_EX_SFUNC:
emit_expr_sfunc(scope, expr, wid);
fprintf(vlog_out, "%s", ivl_expr_name(expr));
emit_expr_func(scope, expr, wid);
break;
case IVL_EX_SIGNAL:
emit_expr_signal(scope, expr, wid);
@ -563,7 +562,8 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
emit_expr_ternary(scope, expr, wid);
break;
case IVL_EX_UFUNC:
emit_expr_ufunc(scope, expr, wid);
emit_scope_path(scope, ivl_expr_def(expr));
emit_expr_func(scope, expr, wid);
break;
case IVL_EX_UNARY:
emit_expr_unary(scope, expr, wid);

View File

@ -232,6 +232,55 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm)
static void emit_logic_as_ca(ivl_scope_t scope, ivl_net_logic_t nlogic);
static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm);
void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex)
{
unsigned idx, count = ivl_nexus_ptrs(nex);
ivl_lpm_t lpm = 0;
ivl_net_const_t net_const = 0;
ivl_net_logic_t net_logic = 0;
ivl_signal_t sig = 0;
for (idx = 0; idx < count; idx += 1) {
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
(ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) continue;
ivl_lpm_t t_lpm = ivl_nexus_ptr_lpm(nex_ptr);
ivl_net_const_t t_net_const = ivl_nexus_ptr_con(nex_ptr);
ivl_net_logic_t t_net_logic = ivl_nexus_ptr_log(nex_ptr);
ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
if (t_lpm) {
assert(! lpm);
lpm = t_lpm;
}
if (t_net_const) {
assert(! net_const);
net_const = t_net_const;
}
if (t_net_logic) {
assert(! net_logic);
net_logic = t_net_logic;
}
if (t_sig) {
assert(! sig);
sig = t_sig;
}
}
if (lpm) {
assert(! net_const);
assert(! net_logic);
assert(! sig);
emit_lpm_as_ca(scope, lpm);
} else if (net_const) {
assert( !net_logic);
assert(! sig);
emit_const_nexus(scope, net_const);
} else if (net_logic) {
assert(! sig);
emit_logic_as_ca(scope, net_logic);
} else if (sig) {
emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0));
} else assert(0);
}
void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex)
{
/* If there is no nexus then there is nothing to print. */
@ -240,6 +289,7 @@ void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex)
if (is_local_nexus(scope, nex)) {
unsigned idx, count = ivl_nexus_ptrs(nex);
unsigned must_be_sig = 0;
unsigned out_of_scope_drive = 0;
ivl_lpm_t lpm = 0;
ivl_net_const_t net_const = 0;
ivl_net_logic_t net_logic = 0;
@ -263,6 +313,10 @@ void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex)
lpm = t_lpm;
}
if (t_net_const) {
if (scope != ivl_const_scope(t_net_const)) {
// HERE: Need to verify that this is not a parameter
out_of_scope_drive = 1;
}
assert(! net_const);
net_const = t_net_const;
}
@ -285,7 +339,15 @@ void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex)
assert( !net_logic);
assert(! sig);
assert(! must_be_sig);
emit_const_nexus(scope, net_const);
if (out_of_scope_drive) {
// HERE: An out of scope const drive that is not a parameter is really a
// port so look for and emit the local signal name (nexus_is_signal
// may work). The is_local_nexus code also needs to be changed to
// not emit the port expressions as a CA. Make sure this works
// correctly if the parameter is passed as a port argument.
// For now report this as missing.
fprintf(vlog_out, "<missing>");
} else emit_const_nexus(scope, net_const);
} else if (net_logic) {
assert(! sig);
assert(! must_be_sig);
@ -385,8 +447,9 @@ static void emit_lpm_array(ivl_scope_t scope, ivl_lpm_t lpm)
{
ivl_signal_t sig = ivl_lpm_array(lpm);
emit_scope_module_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s[", ivl_signal_basename(sig));
// HERE: Need to remove the scale to match array base.
emit_id(ivl_signal_basename(sig));
fprintf(vlog_out, "[");
// HERE: Need to remove the scale to match array base instead of adding it back.
emit_nexus_as_ca(scope, ivl_lpm_select(lpm));
fprintf(vlog_out, " + %d]", ivl_signal_array_base(sig));
}
@ -488,7 +551,7 @@ static void emit_lpm_part_select(ivl_scope_t scope, ivl_lpm_t lpm)
if (base) fprintf(vlog_out, " >> %d)", base);
return;
}
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
emit_id(ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig)) {
array_word += ivl_signal_array_base(sig);
fprintf(vlog_out, "[%d]", array_word);
@ -538,16 +601,19 @@ static void emit_lpm_part_select(ivl_scope_t scope, ivl_lpm_t lpm)
}
// HERE: No support for trigger. Is this actually needed?
static void emit_lpm_func(ivl_scope_t scope, ivl_lpm_t lpm, const char *name)
static void emit_lpm_func(ivl_scope_t scope, ivl_lpm_t lpm)
{
unsigned idx, count= ivl_lpm_size(lpm);
fprintf(vlog_out, "%s(", name);;
for (idx = count-1; idx > 0; idx -= 1) {
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, idx));
fprintf(vlog_out, ", ");
unsigned count = ivl_lpm_size(lpm);
if (count) {
unsigned idx;
fprintf(vlog_out, "(");
for (idx = count-1; idx > 0; idx -= 1) {
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, idx));
fprintf(vlog_out, ", ");
}
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0));
fprintf(vlog_out, ")");
}
emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0));
fprintf(vlog_out, ")");
}
static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm)
@ -692,7 +758,8 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm)
fprintf(vlog_out, "}}");
break;
case IVL_LPM_SFUNC:
emit_lpm_func(scope, lpm, ivl_lpm_string(lpm));
fprintf(vlog_out, "%s", ivl_lpm_string(lpm));
emit_lpm_func(scope, lpm);
break;
case IVL_LPM_SHIFTL:
fprintf(vlog_out, "(");
@ -720,7 +787,8 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm)
fprintf(vlog_out, ")");
break;
case IVL_LPM_UFUNC:
emit_lpm_func(scope, lpm, ivl_scope_name(ivl_lpm_define(lpm)));
emit_scope_path(scope, ivl_lpm_define(lpm));
emit_lpm_func(scope, lpm);
break;
default:
fprintf(vlog_out, "<unknown>");
@ -966,8 +1034,8 @@ static ivl_signal_t get_output_from_nexus(ivl_scope_t scope, ivl_nexus_t nex,
tmp_idx += ivl_signal_array_base(sig);
fprintf(stderr, "[%"PRId64"]", tmp_idx);
}
fprintf(stderr, ") found for nexus ");
fprintf(stderr, "(%s", ivl_signal_basename(use_sig));
fprintf(stderr, ") found for nexus (%s",
ivl_signal_basename(use_sig));
if (is_array) fprintf(stderr, "[%"PRId64"]", *array_idx);
fprintf(stderr, ")\n");
} else {
@ -994,7 +1062,7 @@ static void emit_lpm_part_pv(ivl_scope_t scope, ivl_lpm_t lpm)
&array_word);
assert(sig);
assert(ivl_lpm_data(lpm, 1) == 0);
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
emit_id(ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig)) {
fprintf(vlog_out, "[%"PRId64"]", array_word);
}
@ -1083,7 +1151,7 @@ static void emit_bufz(ivl_scope_t scope, ivl_net_logic_t nlogic)
static void emit_and_save_udp_name(ivl_net_logic_t nlogic){
ivl_udp_t udp = ivl_logic_udp(nlogic);
assert(udp);
fprintf(vlog_out, "%s", ivl_udp_name(udp));
emit_id(ivl_udp_name(udp));
add_udp_to_list(udp);
}
@ -1235,6 +1303,7 @@ void emit_logic(ivl_scope_t scope, ivl_net_logic_t nlogic)
// remove this and rebuild the instance array. For now we just strip
// this encoding and create an zero based range. Need to skip the
// local names _s<digits>.
// This can also be an escaped id.
name = ivl_logic_basename(nlogic);
if (name && *name) {
char *fixed_name = strdup(name);
@ -1246,7 +1315,8 @@ void emit_logic(ivl_scope_t scope, ivl_net_logic_t nlogic)
}
fixed_name[lp] = 0;
}
fprintf(vlog_out, " %s", fixed_name);
fprintf(vlog_out, " ");
emit_id(fixed_name);
free(fixed_name);
if (width > 1) {
fprintf(vlog_out, " [%u:0]", width-1);
@ -1373,7 +1443,9 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
ivl_const_delay(net_const, 1),
ivl_const_delay(net_const, 2),
3);
fprintf(vlog_out, " %s = ", ivl_signal_basename(sig));
fprintf(vlog_out, " ");
emit_id(ivl_signal_basename(sig));
fprintf(vlog_out, " = ");
emit_const_nexus(scope, net_const);
fprintf(vlog_out, ";");
emit_sig_file_line(sig);

View File

@ -16,6 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
# include <ctype.h>
# include <stdlib.h>
# include <string.h>
# include "config.h"
@ -454,8 +455,8 @@ static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
tmp_idx += ivl_signal_array_base(sig);
fprintf(stderr, "[%"PRId64"]", tmp_idx);
}
fprintf(stderr, ") found for nexus ");
fprintf(stderr, "(%s", ivl_signal_basename(use_sig));
fprintf(stderr, ") found for nexus (%s",
ivl_signal_basename(use_sig));
if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
fprintf(stderr, ")\n");
} else {
@ -475,7 +476,7 @@ static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
}
if (use_sig) {
fprintf(vlog_out, "%s", ivl_signal_basename(use_sig));
emit_id(ivl_signal_basename(use_sig));
if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
return 1;
}
@ -530,12 +531,16 @@ static unsigned find_const_nexus(ivl_scope_t scope, ivl_nexus_t nex)
// HERE: Does this work correctly with an array reference created from @*?
void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex)
{
ivl_scope_t mod_scope;
/* First look in the local scope for the nexus name. */
if (find_signal_in_nexus(scope, nex)) return;
/* If the signal was not found in the passed scope then look in
* the module scope if the passed scope was not the module scope. */
if (find_signal_in_nexus(get_module_scope(scope), nex)) return;
mod_scope = get_module_scope(scope);
if (mod_scope != scope) {
if (find_signal_in_nexus(mod_scope, nex)) return;
}
/* If there is no signals driving this then look for a constant. */
if (find_const_nexus(scope, nex)) return;
@ -564,6 +569,19 @@ ivl_scope_t get_module_scope(ivl_scope_t scope)
return scope;
}
static void emit_scope_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_piece(scope, parent);
}
/* Print the base scope. */
emit_id(ivl_scope_basename(call_scope));
fprintf(vlog_out, ".");
}
/*
* This routine emits the appropriate string to call the call_scope from the
* given scope. If the module scopes for the two match then do nothing. If
@ -577,28 +595,8 @@ void emit_scope_module_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) {
/* Trim off the top of the call name if it exactly matches
* the module scope of the caller. */
char *sc_name = strdup(ivl_scope_name(mod_scope));
const char *sc_ptr = sc_name;
char *call_name = strdup(ivl_scope_name(call_mod_scope));
const char *call_ptr = call_name;
while ((*sc_ptr == *call_ptr) &&
(*sc_ptr != 0) && (*call_ptr != 0)) {
sc_ptr += 1;
call_ptr += 1;
}
if (*sc_ptr == 0) {
assert(*call_ptr == '.');
call_ptr += 1;
} else {
call_ptr = call_name;
}
fprintf(vlog_out, "%s.", call_ptr);
free(sc_name);
free(call_name);
}
if (mod_scope == call_mod_scope) return;
emit_scope_piece(mod_scope, call_mod_scope);
}
/* This is the same as emit_scope_module_path() except we need to add down
@ -609,47 +607,35 @@ void emit_scope_call_path(ivl_scope_t scope, ivl_scope_t call_scope)
ivl_scope_t call_mod_scope = get_module_scope(call_scope);
if (mod_scope != call_mod_scope) {
/* Trim off the top of the call name if it exactly matches
* the module scope of the caller. */
char *sc_name = strdup(ivl_scope_name(mod_scope));
const char *sc_ptr = sc_name;
char *call_name = strdup(ivl_scope_name(call_mod_scope));
const char *call_ptr = call_name;
while ((*sc_ptr == *call_ptr) &&
(*sc_ptr != 0) && (*call_ptr != 0)) {
sc_ptr += 1;
call_ptr += 1;
}
if (*sc_ptr == 0) {
assert(*call_ptr == '.');
call_ptr += 1;
} else {
call_ptr = call_name;
}
fprintf(vlog_out, "%s.", call_ptr);
free(sc_name);
free(call_name);
emit_scope_piece(mod_scope, call_mod_scope);
} else if (scope != call_scope) {
/* Look for a down reference that is local to the module scope. */
char *sc_name = strdup(ivl_scope_name(scope));
const char *sc_ptr = sc_name;
char *call_name = strdup(ivl_scope_name(call_scope));
const char *call_ptr = call_name;
while ((*sc_ptr == *call_ptr) &&
(*sc_ptr != 0) && (*call_ptr != 0)) {
sc_ptr += 1;
call_ptr += 1;
ivl_scope_t parent;
/* We only emit a scope path if the scope is a parent of the
* call scope. */
for (parent = ivl_scope_parent(call_scope);
parent != 0;
parent = ivl_scope_parent(parent)) {
if (parent == scope) {
emit_scope_piece(scope, call_scope);
return;
}
}
if (*sc_ptr == 0) {
assert(*call_ptr == '.');
call_ptr += 1;
fprintf(vlog_out, "%s.", call_ptr);
}
free(sc_name);
free(call_name);
}
}
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));
}
/*
* 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
@ -664,27 +650,32 @@ void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope)
ivl_scope_t call_mod_scope = get_module_scope(call_scope);
if (mod_scope == call_mod_scope) {
fprintf(vlog_out, "%s", ivl_scope_basename(call_scope));
emit_id(ivl_scope_basename(call_scope));
} else {
/* Trim off the top of the call name if it exactly matches
* the module scope of the caller. */
char *sc_name = strdup(ivl_scope_name(mod_scope));
const char *sc_ptr = sc_name;
char *call_name = strdup(ivl_scope_name(call_scope));
const char *call_ptr = call_name;
while ((*sc_ptr == *call_ptr) &&
(*sc_ptr != 0) && (*call_ptr != 0)) {
sc_ptr += 1;
call_ptr += 1;
}
if (*sc_ptr == 0) {
assert(*call_ptr == '.');
call_ptr += 1;
} else {
call_ptr = call_name;
}
fprintf(vlog_out, "%s", call_ptr);
free(sc_name);
free(call_name);
emit_scope_path_piece(mod_scope, call_scope);
}
}
static unsigned is_escaped(const char *id)
{
assert(id);
/* The first digit must be alpha or '_' to be a normal id. */
if (isalpha((int)id[0]) || id[0] == '_') {
unsigned idx;
for (idx = 1; id[idx] != '\0'; idx += 1) {
if (! (isalnum((int)id[idx]) ||
id[idx] == '_' || id[idx] == '$')) {
return 1;
}
}
/* We looked at all the digits, so this is a normal id. */
return 0;
}
return 1;
}
void emit_id(const char *id)
{
if (is_escaped(id)) fprintf(vlog_out, "\\%s ", id);
else fprintf(vlog_out, "%s", id);
}

View File

@ -51,7 +51,7 @@ static int32_t get_int32_from_bits(const char *bits, unsigned nbits,
else if (bits[idx] != '0') {
*result_type = -1;
/* If the value is entirely x/z then return -2 or -3. */
if ((idx == 0) && (trim_wid == 1)) {
if (trim_wid == 1) {
if (bits[idx] == 'x') *result_type -= 1;
*result_type -= 1;
}
@ -190,7 +190,7 @@ uint64_t get_uint64_from_number(ivl_expr_t expr, int *result_type)
else if (bits[idx] != '0') {
*result_type = -1;
/* If the value is entirely x/z then return -2 or -3. */
if ((idx == 0) && (trim_wid == 1)) {
if (trim_wid == 1) {
if (bits[idx] == 'x') *result_type -= 1;
*result_type -= 1;
}
@ -236,7 +236,7 @@ int64_t get_int64_from_number(ivl_expr_t expr, int *result_type)
else if (bits[idx] != '0') {
*result_type = -1;
/* If the value is entirely x/z then return -2 or -3. */
if ((idx == 0) && (trim_wid == 1)) {
if (trim_wid == 1) {
if (bits[idx] == 'x') *result_type -= 1;
*result_type -= 1;
}

View File

@ -76,14 +76,21 @@ void emit_sig_file_line(ivl_signal_t sig)
}
}
static void emit_sig_id(ivl_signal_t sig)
{
emit_id(ivl_signal_basename(sig));
fprintf(vlog_out, ";");
emit_sig_file_line(sig);
fprintf(vlog_out, "\n");
}
void emit_var_def(ivl_signal_t sig)
{
if (ivl_signal_local(sig)) return;
fprintf(vlog_out, "%*c", indent, ' ');
if (ivl_signal_integer(sig)) {
fprintf(vlog_out, "integer %s;", ivl_signal_basename(sig));
emit_sig_file_line(sig);
fprintf(vlog_out, "\n");
fprintf(vlog_out, "integer ");
emit_sig_id(sig);
if (ivl_signal_dimensions(sig) > 0) {
fprintf(stderr, "%s:%u: vlog95 error: Integer arrays (%s) "
"are not supported.\n", ivl_signal_file(sig),
@ -92,9 +99,8 @@ void emit_var_def(ivl_signal_t sig)
vlog_errors += 1;
}
} else if (ivl_signal_data_type(sig) == IVL_VT_REAL) {
fprintf(vlog_out, "real %s;", ivl_signal_basename(sig));
emit_sig_file_line(sig);
fprintf(vlog_out, "\n");
fprintf(vlog_out, "real ");
emit_sig_id(sig);
if (ivl_signal_dimensions(sig) > 0) {
fprintf(stderr, "%s:%u: vlog95 error: Real arrays (%s) "
"are not supported.\n", ivl_signal_file(sig),
@ -105,9 +111,9 @@ void emit_var_def(ivl_signal_t sig)
} else {
int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig);
fprintf(vlog_out, "reg");
if (msb != 0 || lsb != 0) fprintf(vlog_out, " [%d:%d]", msb, lsb);
fprintf(vlog_out, " %s", ivl_signal_basename(sig));
fprintf(vlog_out, "reg ");
if (msb != 0 || lsb != 0) fprintf(vlog_out, "[%d:%d] ", msb, lsb);
emit_id(ivl_signal_basename(sig));
if (ivl_signal_dimensions(sig) > 0) {
unsigned wd_count = ivl_signal_array_count(sig);
int first = ivl_signal_array_base(sig);
@ -178,23 +184,24 @@ void emit_net_def(ivl_scope_t scope, ivl_signal_t sig)
if (ivl_signal_local(sig)) return;
fprintf(vlog_out, "%*c", indent, ' ');
if (ivl_signal_data_type(sig) == IVL_VT_REAL){
fprintf(vlog_out, "wire %s;\n", ivl_signal_basename(sig));
fprintf(vlog_out, "wire ");
emit_sig_id(sig);
fprintf(stderr, "%s:%u: vlog95 error: Real nets (%s) are "
"not supported.\n", ivl_signal_file(sig),
ivl_signal_lineno(sig), ivl_signal_basename(sig));
vlog_errors += 1;
} else if (ivl_signal_signed(sig)) {
fprintf(vlog_out, "wire");
if (msb != 0 || lsb != 0) fprintf(vlog_out, " [%d:%d]", msb, lsb);
fprintf(vlog_out, " %s;\n", ivl_signal_basename(sig));
fprintf(vlog_out, "wire ");
if (msb != 0 || lsb != 0) fprintf(vlog_out, "[%d:%d] ", msb, lsb);
emit_sig_id(sig);
fprintf(stderr, "%s:%u: vlog95 error: Signed nets (%s) are "
"not supported.\n", ivl_signal_file(sig),
ivl_signal_lineno(sig), ivl_signal_basename(sig));
vlog_errors += 1;
} else if (ivl_signal_dimensions(sig) > 0) {
fprintf(vlog_out, "wire");
if (msb != 0 || lsb != 0) fprintf(vlog_out, " [%d:%d]", msb, lsb);
fprintf(vlog_out, " %s;\n", ivl_signal_basename(sig));
fprintf(vlog_out, "wire ");
if (msb != 0 || lsb != 0) fprintf(vlog_out, "[%d:%d] ", msb, lsb);
emit_sig_id(sig);
fprintf(stderr, "%s:%u: vlog95 error: Array nets (%s) are "
"not supported.\n", ivl_signal_file(sig),
ivl_signal_lineno(sig), ivl_signal_basename(sig));
@ -205,59 +212,58 @@ void emit_net_def(ivl_scope_t scope, ivl_signal_t sig)
case IVL_SIT_UWIRE:
// HERE: Need to add support for supply nets. Probably supply strength
// with a constant 0/1 driver for all the bits.
fprintf(vlog_out, "wire");
fprintf(vlog_out, "wire ");
break;
case IVL_SIT_TRI0:
fprintf(vlog_out, "tri0");
fprintf(vlog_out, "tri0 ");
break;
case IVL_SIT_TRI1:
fprintf(vlog_out, "tri1");
fprintf(vlog_out, "tri1 ");
break;
case IVL_SIT_TRIAND:
fprintf(vlog_out, "wand");
fprintf(vlog_out, "wand ");
break;
case IVL_SIT_TRIOR:
fprintf(vlog_out, "wor");
fprintf(vlog_out, "wor ");
break;
default:
fprintf(vlog_out, "<unknown>");
fprintf(vlog_out, "<unknown> ");
fprintf(stderr, "%s:%u: vlog95 error: Unknown net type "
"(%d).\n", ivl_signal_file(sig),
ivl_signal_lineno(sig), (int)ivl_signal_type(sig));
vlog_errors += 1;
break;
}
if (msb != 0 || lsb != 0) fprintf(vlog_out, " [%d:%d]", msb, lsb);
fprintf(vlog_out, " %s;", ivl_signal_basename(sig));
emit_sig_file_line(sig);
fprintf(vlog_out, "\n");
if (msb != 0 || lsb != 0) fprintf(vlog_out, "[%d:%d] ", msb, lsb);
emit_sig_id(sig);
/* A constant driving a net does not create an lpm or logic
* element in the design so save them from the definition. */
save_net_constants(scope, sig);
}
}
static char *get_mangled_name(ivl_scope_t scope, unsigned root)
static void emit_mangled_name(ivl_scope_t scope, unsigned root)
{
char *name;
/* If the module has parameters and it's not a root module then it
* may not be unique so we create a mangled name version instead. */
* may not be unique so we create a mangled name version instead.
* The mangled name is of the form:
* <module_name>[<full_instance_scope>]. */
if (ivl_scope_params(scope) && ! root) {
unsigned idx;
char *name;
size_t len = strlen(ivl_scope_name(scope)) +
strlen(ivl_scope_tname(scope)) + 2;
strlen(ivl_scope_tname(scope)) + 3;
name = (char *)malloc(len);
(void) strcpy(name, ivl_scope_tname(scope));
(void) strcat(name, "_");
(void) strcat(name, "[");
(void) strcat(name, ivl_scope_name(scope));
(void) strcat(name, "]");
assert(name[len-1] == 0);
for (idx = 0; idx < len; idx += 1) {
if (name[idx] == '.') name[idx] = '_';
}
/* Emit the mangled name as an escaped identifier. */
fprintf(vlog_out, "\\%s ", name);
free(name);
} else {
name = strdup(ivl_scope_tname(scope));
emit_id(ivl_scope_tname(scope));
}
return name;
}
/*
@ -279,8 +285,9 @@ void emit_scope_variables(ivl_scope_t scope)
for (idx = 0; idx < count; idx += 1) {
ivl_parameter_t par = ivl_scope_param(scope, idx);
ivl_expr_t pex = ivl_parameter_expr(par);
fprintf(vlog_out, "%*cparameter %s = ", indent, ' ',
ivl_parameter_basename(par));
fprintf(vlog_out, "%*cparameter ", indent, ' ');
emit_id(ivl_parameter_basename(par));
fprintf(vlog_out, " = ");
emit_expr(scope, pex, 0);
fprintf(vlog_out, ";");
if (emit_file_line) {
@ -317,8 +324,9 @@ void emit_scope_variables(ivl_scope_t scope)
if (ivl_event_nany(event)) continue;
if (ivl_event_npos(event)) continue;
if (ivl_event_nneg(event)) continue;
fprintf(vlog_out, "%*cevent %s;", indent, ' ',
ivl_event_basename(event));
fprintf(vlog_out, "%*cevent ", indent, ' ');
emit_id(ivl_event_basename(event));
fprintf(vlog_out, ";");
if (emit_file_line) {
fprintf(vlog_out, " /* %s:%u */",
ivl_event_file(event),
@ -345,65 +353,166 @@ static void emit_module_ports(ivl_scope_t scope)
if (count == 0) return;
fprintf(stderr, "%s:%u: vlog95 sorry: Modules with port are not "
"currently supported.\n", ivl_scope_file(scope),
ivl_scope_lineno(scope));
vlog_errors += 1;
fprintf(vlog_out, "(");
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, 0));
for (idx = 1; idx < count; idx += 1) {
fprintf(vlog_out, ", ");
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, idx));
// HERE: Save the signals that are connected to the nexi and use those
// in the port_def code below.
}
fprintf(vlog_out, ")");
}
static ivl_signal_t get_port_from_nexus(ivl_scope_t scope, ivl_nexus_t nex)
{
assert(nex);
unsigned idx, count = ivl_nexus_ptrs(nex);
ivl_signal_t sig = 0;
for (idx = 0; idx < count; idx += 1) {
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
if (t_sig) {
if (ivl_signal_scope(t_sig) != scope) continue;
assert(! sig);
sig = t_sig;
}
}
return sig;
}
static void emit_sig_type(ivl_signal_t sig)
{
ivl_signal_type_t type = ivl_signal_type(sig);
assert(ivl_signal_dimensions(sig) == 0);
/* Check to see if we have a variable (reg) or a net. */
if (type == IVL_SIT_REG) {
if (ivl_signal_integer(sig)) {
fprintf(vlog_out, " integer");
} else if (ivl_signal_data_type(sig) == IVL_VT_REAL) {
fprintf(vlog_out, " real");
} else {
int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig);
if (msb != 0 || lsb != 0) {
fprintf(vlog_out, " [%d:%d]", msb, lsb);
}
if (ivl_signal_signed(sig)) {
fprintf(stderr, "%s:%u: vlog95 error: Signed ports "
"(%s) are not supported.\n",
ivl_signal_file(sig),
ivl_signal_lineno(sig),
ivl_signal_basename(sig));
vlog_errors += 1;
}
}
} else {
assert(type == IVL_SIT_TRI);
if (ivl_signal_data_type(sig) == IVL_VT_REAL) {
fprintf(stderr, "%s:%u: vlog95 error: Real net ports (%s) "
"are not supported.\n",
ivl_signal_file(sig),
ivl_signal_lineno(sig),
ivl_signal_basename(sig));
vlog_errors += 1;
} else {
int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig);
if (ivl_signal_signed(sig)) {
fprintf(stderr, "%s:%u: vlog95 error: Signed net ports "
"(%s) are not supported.\n",
ivl_signal_file(sig),
ivl_signal_lineno(sig),
ivl_signal_basename(sig));
vlog_errors += 1;
}
if (msb != 0 || lsb != 0) {
fprintf(vlog_out, " [%d:%d]", msb, lsb);
}
}
}
}
static void emit_port(ivl_signal_t port)
{
assert(port);
fprintf(vlog_out, "%*c", indent, ' ');
switch (ivl_signal_port(port)) {
case IVL_SIP_INPUT:
fprintf(vlog_out, "input");
break;
case IVL_SIP_OUTPUT:
fprintf(vlog_out, "output");
break;
case IVL_SIP_INOUT:
fprintf(vlog_out, "inout");
break;
default:
fprintf(vlog_out, "<unknown>");
fprintf(stderr, "%s:%u: vlog95 error: Unknown port direction (%d) "
"for signal %s.\n", ivl_signal_file(port),
ivl_signal_lineno(port), (int)ivl_signal_port(port),
ivl_signal_basename(port));
vlog_errors += 1;
break;
}
emit_sig_type(port);
fprintf(vlog_out, " ");
emit_id(ivl_signal_basename(port));
fprintf(vlog_out, ";");
emit_sig_file_line(port);
fprintf(vlog_out, "\n");
}
static void emit_module_port_defs(ivl_scope_t scope)
{
unsigned idx, count = ivl_scope_ports(scope);
for (idx = 0; idx < count; idx += 1) {
ivl_nexus_t port = ivl_scope_mod_port(scope, idx);
fprintf(vlog_out, "%*c", indent, ' ');
// HERE: Need port type/size information.
emit_nexus_as_ca(scope, port);
// emit_sig_file_line(port);
fprintf(vlog_out, " \n");
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
ivl_signal_t port = get_port_from_nexus(scope, nex);
if (port) emit_port(port);
else {
fprintf(vlog_out, "<missing>");
fprintf(stderr, "%s:%u: vlog95 error: Could not find signal "
"definition for port (%u) of module %s.\n",
ivl_scope_file(scope), ivl_scope_lineno(scope),
idx + 1, ivl_scope_basename(scope));
vlog_errors += 1;
}
}
if (count) fprintf(vlog_out, "\n");
}
static void emit_module_call_expr(ivl_scope_t scope, unsigned idx)
{
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
ivl_signal_t port = get_port_from_nexus(scope, nex);
/* For an input port we need to emit the driving expression. */
if (ivl_signal_port(port) == IVL_SIP_INPUT) {
emit_nexus_port_driver_as_ca(ivl_scope_parent(scope),
ivl_signal_nex(port, 0));
/* For an output we need to emit the signal the output is driving. */
} else {
emit_nexus_as_ca(ivl_scope_parent(scope), ivl_signal_nex(port, 0));
}
}
static void emit_module_call_expressions(ivl_scope_t scope)
{
unsigned idx, count = ivl_scope_ports(scope);
if (count == 0) return;
emit_module_call_expr(scope, 0);
for (idx = 1; idx < count; idx += 1) {
fprintf(vlog_out, ", ");
emit_module_call_expr(scope, idx);
}
}
static void emit_task_func_port_defs(ivl_scope_t scope)
{
unsigned idx, count = ivl_scope_ports(scope);
unsigned start = ivl_scope_type(scope) == IVL_SCT_FUNCTION;
for (idx = start; idx < count; idx += 1) {
ivl_signal_t port = ivl_scope_port(scope, idx);
fprintf(vlog_out, "%*c", indent, ' ');
switch (ivl_signal_port(port)) {
case IVL_SIP_INPUT:
fprintf(vlog_out, "input");
break;
case IVL_SIP_OUTPUT:
fprintf(vlog_out, "output");
break;
case IVL_SIP_INOUT:
fprintf(vlog_out, "inout");
break;
default:
fprintf(vlog_out, "<unknown>");
fprintf(stderr, "%s:%u: vlog95 error: Unknown port "
"direction (%d) for signal %s.\n",
ivl_signal_file(port), ivl_signal_lineno(port),
(int)ivl_signal_port(port),
ivl_signal_basename(port));
vlog_errors += 1;
break;
}
fprintf(vlog_out, " %s;", ivl_signal_basename(port));
emit_sig_file_line(port);
fprintf(vlog_out, " \n");
emit_port(port);
}
if (count) fprintf(vlog_out, "\n");
}
@ -454,25 +563,25 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
ivl_scope_type_t sc_type = ivl_scope_type(scope);
unsigned is_auto = ivl_scope_is_auto(scope);
unsigned idx, count;
char *name;
/* Output the scope definition. */
switch (sc_type) {
case IVL_SCT_MODULE:
assert(!is_auto);
name = get_mangled_name(scope, !parent && !emitting_scopes);
/* This is an instantiation. */
if (parent) {
assert(indent != 0);
/* If the module has parameters then it may not be unique
* so we create a mangled name version instead. */
fprintf(vlog_out, "\n%*c%s %s(", indent, ' ', name,
ivl_scope_basename(scope));
// HERE: Still need to add port information.
fprintf(vlog_out, "\n%*c", indent, ' ');
emit_mangled_name(scope, !parent && !emitting_scopes);
fprintf(vlog_out, " ");
emit_id(ivl_scope_basename(scope));
fprintf(vlog_out, "(");
emit_module_call_expressions(scope);
fprintf(vlog_out, ");");
emit_scope_file_line(scope);
fprintf(vlog_out, "\n");
free(name);
num_scopes_to_emit += 1;
scopes_to_emit = realloc(scopes_to_emit, num_scopes_to_emit *
sizeof(ivl_scope_t));
@ -491,8 +600,8 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
"file %s at line %u. */\n",
ivl_scope_def_file(scope),
ivl_scope_def_lineno(scope));
fprintf(vlog_out, "module %s", name);
free(name);
fprintf(vlog_out, "module ");
emit_mangled_name(scope, !parent && !emitting_scopes);
emit_module_ports(scope);
break;
case IVL_SCT_FUNCTION:
@ -501,7 +610,8 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
assert(ivl_scope_ports(scope) >= 2);
/* The function return information is the zero port. */
emit_func_return(ivl_scope_port(scope, 0));
fprintf(vlog_out, " %s", ivl_scope_tname(scope));
fprintf(vlog_out, " ");
emit_id(ivl_scope_tname(scope));
if (is_auto) {
fprintf(stderr, "%s:%u: vlog95 error: Automatic functions "
"(%s) are not supported.\n", ivl_scope_file(scope),
@ -511,8 +621,8 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
break;
case IVL_SCT_TASK:
assert(indent != 0);
fprintf(vlog_out, "\n%*ctask %s", indent, ' ',
ivl_scope_tname(scope));
fprintf(vlog_out, "\n%*ctask ", indent, ' ');
emit_id(ivl_scope_tname(scope));
if (is_auto) {
fprintf(stderr, "%s:%u: vlog95 error: Automatic tasks "
"(%s) are not supported.\n", ivl_scope_file(scope),
@ -583,7 +693,9 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
switch (sc_type) {
case IVL_SCT_MODULE:
assert(indent == 0);
fprintf(vlog_out, "endmodule /* %s */\n", ivl_scope_tname(scope));
fprintf(vlog_out, "endmodule /* ");
emit_mangled_name(scope, !parent && !emitting_scopes);
fprintf(vlog_out, " */\n");
if (ivl_scope_is_cell(scope)) {
fprintf(vlog_out, "`endcelldefine\n");
}

View File

@ -91,7 +91,7 @@ static void emit_stmt_lval_name(ivl_scope_t scope, ivl_lval_t lval,
{
ivl_expr_t array_idx = ivl_lval_idx(lval);
emit_scope_call_path(scope, ivl_signal_scope(sig));
fprintf(vlog_out, "%s", ivl_signal_basename(sig));
emit_id(ivl_signal_basename(sig));
if (array_idx) {
int msb, lsb;
assert(ivl_signal_dimensions(sig));
@ -767,8 +767,8 @@ static void emit_stmt_block(ivl_scope_t scope, ivl_statement_t stmt)
static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
{
ivl_scope_t my_scope = ivl_stmt_block_scope(stmt);
fprintf(vlog_out, "%*cbegin: %s", get_indent(), ' ',
ivl_scope_basename(my_scope));
fprintf(vlog_out, "%*cbegin: ", get_indent(), ' ');
emit_id(ivl_scope_basename(my_scope));
emit_stmt_file_line(stmt);
fprintf(vlog_out, "\n");
emit_stmt_block_body(scope, stmt);
@ -778,23 +778,23 @@ static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt)
static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
{
char *name;
char *case_type;
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
switch(ivl_statement_type(stmt)) {
case IVL_ST_CASE:
case IVL_ST_CASER:
name = "case";
case_type = "case";
break;
case IVL_ST_CASEX:
name = "casex";
case_type = "casex";
break;
case IVL_ST_CASEZ:
name = "casez";
case_type = "casez";
break;
default:
assert(0);
}
fprintf(vlog_out, "%*c%s (", get_indent(), ' ', name);
fprintf(vlog_out, "%*c%s (", get_indent(), ' ', case_type);
emit_expr(scope, ivl_stmt_cond_expr(stmt), 0);
fprintf(vlog_out, ")");
emit_stmt_file_line(stmt);
@ -949,8 +949,8 @@ static void emit_stmt_fork(ivl_scope_t scope, ivl_statement_t stmt)
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: %s", get_indent(), ' ',
ivl_scope_basename(my_scope));
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);

View File

@ -183,24 +183,30 @@ static void emit_udp(ivl_udp_t udp)
fprintf(vlog_out, "/* This primitive was originally defined in "
"file %s at line %u. */\n",
ivl_udp_file(udp), ivl_udp_lineno(udp));
fprintf(vlog_out, "primitive %s (", ivl_udp_name(udp));
fprintf(vlog_out, "%s", ivl_udp_port(udp, 0));
fprintf(vlog_out, "primitive ");
emit_id(ivl_udp_name(udp));
fprintf(vlog_out, " (");
emit_id(ivl_udp_port(udp, 0));
count = ivl_udp_nin(udp);
for (idx = 1; idx <= count; idx += 1) {
fprintf(vlog_out, ", %s", ivl_udp_port(udp, idx));
fprintf(vlog_out, ", ");
emit_id(ivl_udp_port(udp, idx));
}
fprintf(vlog_out, ");\n");
fprintf(vlog_out, "%*coutput %s;\n", indent_incr, ' ',
ivl_udp_port(udp, 0));
fprintf(vlog_out, "%*coutput ", indent_incr, ' ');
emit_id(ivl_udp_port(udp, 0));
fprintf(vlog_out, ";\n");
for (idx = 1; idx <= count; idx += 1) {
fprintf(vlog_out, "%*cinput %s;\n", indent_incr, ' ',
ivl_udp_port(udp, idx));
fprintf(vlog_out, "%*cinput ", indent_incr, ' ');
emit_id(ivl_udp_port(udp, idx));
fprintf(vlog_out, ";\n");
}
if (ivl_udp_sequ(udp)) {
char init = ivl_udp_init(udp);
fprintf(vlog_out, "\n");
fprintf(vlog_out, "%*creg %s;\n", indent_incr, ' ',
ivl_udp_port(udp, 0));
fprintf(vlog_out, "%*creg ", indent_incr, ' ');
emit_id(ivl_udp_port(udp, 0));
fprintf(vlog_out, ";\n");
switch (init) {
case '0':
case '1':
@ -209,8 +215,9 @@ static void emit_udp(ivl_udp_t udp)
init = 'x';
break;
}
fprintf(vlog_out, "%*cinitial %s = 1'b%c;\n",
indent_incr, ' ', ivl_udp_port(udp, 0), init);
fprintf(vlog_out, "%*cinitial ", indent_incr, ' ');
emit_id(ivl_udp_port(udp, 0));
fprintf(vlog_out, " = 1'b%c;\n", init);
}
fprintf(vlog_out, "\n");
fprintf(vlog_out, "%*ctable\n", indent_incr, ' ');

View File

@ -81,6 +81,7 @@ extern void emit_scope_call_path(ivl_scope_t scope, ivl_scope_t call_scope);
extern void emit_scope_module_path(ivl_scope_t scope, ivl_scope_t call_scope);
extern void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex);
extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex);
extern void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex);
extern void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t const_net);
extern void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig);
extern void emit_icarus_generated_udps();
@ -89,6 +90,7 @@ extern void add_udp_to_list(ivl_udp_t udp);
extern void emit_udp_list();
extern void emit_sig_file_line(ivl_signal_t sig);
extern void emit_id(const char *id);
extern void emit_real_number(double value);
extern void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
const char *file, unsigned lineno);