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.
This commit is contained in:
Cary R 2011-04-18 11:18:04 -07:00 committed by Stephen Williams
parent 2158ebdf0b
commit 8b8e181fe2
4 changed files with 120 additions and 26 deletions

View File

@ -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;
}

View File

@ -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, ")");
}
}

View File

@ -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, "<invalid>");
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;
}
}

View File

@ -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;