From 8b8e181fe2d55f27bd129f2a56a9d58754e59ac0 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 18 Apr 2011 11:18:04 -0700 Subject: [PATCH] vlog95: Print structural string constants and a few other fixes This patch adds the ability to print a constant string in a structural context. It also fixes the argument order for structural function calls and makes a few improvements in nexus identification. --- tgt-vlog95/expr.c | 6 ++- tgt-vlog95/logic_lpm.c | 22 ++++---- tgt-vlog95/misc.c | 116 ++++++++++++++++++++++++++++++++++++----- tgt-vlog95/numbers.c | 2 +- 4 files changed, 120 insertions(+), 26 deletions(-) diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index 2defb1d84..0210809c9 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -244,7 +244,7 @@ static void emit_expr_scope(ivl_scope_t scope, ivl_expr_t expr, unsigned wid) static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr) { unsigned idx, count, lineno; - const char* file; + const char *file; count = ivl_scope_params(scope); file = ivl_expr_file(expr); lineno = ivl_expr_lineno(expr); @@ -253,7 +253,7 @@ static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr) if (lineno != ivl_parameter_lineno(par)) continue; if (strcmp(file, ivl_parameter_file(par)) == 0) { /* Check that the appropriate expression bits match the - * the original parameter bits. */ + * original parameter bits. */ ivl_expr_t pex = ivl_parameter_expr(par); unsigned wid = ivl_expr_width(expr); unsigned param_wid = ivl_expr_width(pex); @@ -271,6 +271,8 @@ static unsigned emit_param_name_in_scope(ivl_scope_t scope, ivl_expr_t expr) break; } } +// HERE: Does this work with an out of scope parameter reference? +// What about real parameters? emit_id(ivl_parameter_basename(par)); return 1; } diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index b3731588a..9196e757a 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -242,9 +242,9 @@ static void emit_nexus_port_signal(ivl_scope_t scope, ivl_nexus_t 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 ((ivl_nexus_ptr_drive1(nex_ptr) != IVL_DR_HiZ) || (ivl_nexus_ptr_drive0(nex_ptr) != IVL_DR_HiZ)) assert(0); - ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr); if (t_sig) { if (scope != ivl_signal_scope(t_sig)) continue; assert(! sig); @@ -256,6 +256,9 @@ static void emit_nexus_port_signal(ivl_scope_t scope, ivl_nexus_t nex) else fprintf(vlog_out, "/* Empty */"); } +/* + * Emit the input port driving expression. + */ void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex) { unsigned idx, count = ivl_nexus_ptrs(nex); @@ -265,12 +268,12 @@ void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex) 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 ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) && + (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) continue; if (t_lpm) { assert(! lpm); lpm = t_lpm; @@ -325,6 +328,10 @@ void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t 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_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 ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) && (ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ)) { /* If we only have a single input then we want @@ -333,10 +340,6 @@ void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex) must_be_sig = 1; } else 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; @@ -660,12 +663,13 @@ static void emit_lpm_func(ivl_scope_t scope, ivl_lpm_t lpm) unsigned count = ivl_lpm_size(lpm); if (count) { unsigned idx; + count -= 1; fprintf(vlog_out, "("); - for (idx = count-1; idx > 0; idx -= 1) { + for (idx = 0; idx < count; 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)); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, count)); fprintf(vlog_out, ")"); } } diff --git a/tgt-vlog95/misc.c b/tgt-vlog95/misc.c index 84e188a25..e9acba726 100644 --- a/tgt-vlog95/misc.c +++ b/tgt-vlog95/misc.c @@ -484,27 +484,115 @@ static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex) return 0; } -void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t const_net) +static void emit_number_as_string(ivl_net_const_t net_const) { - switch (ivl_const_type(const_net)) { + const char *bits = ivl_const_bits(net_const); + unsigned count = ivl_const_width(net_const); + int idx; + + assert((count % 8) == 0); + fprintf(vlog_out, "\""); + for (idx = (int)count-1; idx >= 0; idx -= 8) { + unsigned bit; + char val = 0; + for (bit = 0; bit < 8; bit += 1) { + val |= (bits[idx-bit] == '1') ? 1 << (7-bit) : 0x00; + } + + /* Skip any NULL bytes. */ + if (val == 0) continue; + /* Print some values that must be escapped. */ + if (val == '"') fprintf(vlog_out, "\\\""); + else if (val == '\\') fprintf(vlog_out, "\\\\"); + /* Print the printable characters. */ + else if (isprint(val)) fprintf(vlog_out, "%c", val); + /* Print the non-printable characters as an octal escape. */ + else fprintf(vlog_out, "\\%03o", val); + } + fprintf(vlog_out, "\""); +} + +static unsigned emit_as_input(ivl_scope_t scope, ivl_net_const_t net_const) +{ + ivl_scope_t const_scope = ivl_const_scope(net_const); + ivl_scope_t parent = ivl_scope_parent(scope); + + /* Look to see if the constant scope is a parent of this scope. */ + while (parent) { + if (parent == const_scope) break; + parent = ivl_scope_parent(parent); + } + + /* If the constant scope is a parent then look for an input in + * this scope and use that for the name. */ + if (parent) { + ivl_nexus_t nex = ivl_const_nex(net_const); + unsigned idx, count = ivl_nexus_ptrs(nex); + for (idx = 0; idx < count; idx += 1) { + ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); + ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr); + if (sig && (ivl_signal_port(sig) == IVL_SIP_INPUT)) { + emit_id(ivl_signal_basename(sig)); + return 1; + } + } + } + + return 0; +} + +void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t net_const) +{ + ivl_scope_t const_scope = ivl_const_scope(net_const); + unsigned idx, count, lineno; + const char *file; + count = ivl_scope_params(const_scope); + file = ivl_const_file(net_const); + lineno = ivl_const_lineno(net_const); + /* Look to see if the constant matches a parameter in its scope. */ + for (idx = 0; idx < count; idx += 1) { + ivl_parameter_t par = ivl_scope_param(const_scope, idx); + if (lineno != ivl_parameter_lineno(par)) continue; + if (strcmp(file, ivl_parameter_file(par)) == 0) { + /* Check that the appropriate expression bits match the + * original parameter bits. */ +// HERE: Verify that the values match and then print the name. +// Does this work with out of scope references? Check real parameters. + emit_id(ivl_parameter_basename(par)); + return; + } + } + + /* If the scopes don't match then we assume this is an empty port. */ + if (const_scope != scope) { + /* This constant could really be from an input port. */ + if (emit_as_input(scope, net_const)) return; + fprintf(vlog_out, "/* Empty */"); + return; + } + + switch (ivl_const_type(net_const)) { case IVL_VT_LOGIC: case IVL_VT_BOOL: - emit_number(ivl_const_bits(const_net), - ivl_const_width(const_net), - ivl_const_signed(const_net), - ivl_const_file(const_net), - ivl_const_lineno(const_net)); + emit_number(ivl_const_bits(net_const), + ivl_const_width(net_const), + ivl_const_signed(net_const), + ivl_const_file(net_const), + ivl_const_lineno(net_const)); + break; + case IVL_VT_STRING: + emit_number_as_string(net_const); break; case IVL_VT_REAL: - emit_real_number(ivl_const_real(const_net)); + emit_real_number(ivl_const_real(net_const)); break; default: fprintf(vlog_out, ""); fprintf(stderr, "%s:%u: vlog95 error: Unknown constant type " "(%d).\n", - ivl_const_file(const_net), - ivl_const_lineno(const_net), - (int)ivl_const_type(const_net)); + ivl_const_file(net_const), + ivl_const_lineno(net_const), + (int)ivl_const_type(net_const)); vlog_errors += 1; break; } @@ -517,11 +605,11 @@ static unsigned find_const_nexus(ivl_scope_t scope, ivl_nexus_t nex) count = ivl_nexus_ptrs(nex); for (idx = 0; idx < count; idx += 1) { ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); - ivl_net_const_t const_net = ivl_nexus_ptr_con(nex_ptr); + ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr); // HERE: Do we need to check for duplicates? - if (const_net) { + if (net_const) { assert(! ivl_nexus_ptr_pin(nex_ptr)); - emit_const_nexus(scope, const_net); + emit_const_nexus(scope, net_const); return 1; } } diff --git a/tgt-vlog95/numbers.c b/tgt-vlog95/numbers.c index 7ea1b37f6..2dd1bc1af 100644 --- a/tgt-vlog95/numbers.c +++ b/tgt-vlog95/numbers.c @@ -77,7 +77,7 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed) unsigned has_undef = 0; /* Check for an undefined bit. */ - for (idx = (int)nbits -1; idx >= 0; idx -= 1) { + for (idx = (int)nbits-1; idx >= 0; idx -= 1) { if ((bits[idx] != '0') && (bits[idx] != '1')) { has_undef = 1; break;