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:
parent
2158ebdf0b
commit
8b8e181fe2
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, ")");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue