vlog95: Major rework of nexus emitting code, etc.
Rework the nexus emitting code to correctly translate most I/O ports. Fix a few other expression issues uncovered when port translation was done correctly. Ignore and warn that the SV ++/-- operators and enum types are not translatable. More updates of the nexus debug code.
This commit is contained in:
parent
a433fa3fcd
commit
dab982f39b
|
|
@ -36,7 +36,7 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
if (first) first = 0;
|
if (first) first = 0;
|
||||||
else fprintf(vlog_out, " or ");
|
else fprintf(vlog_out, " or ");
|
||||||
emit_name_of_nexus(scope, ivl_event_any(event, idx));
|
emit_nexus_as_ca(scope, ivl_event_any(event, idx), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for positive edge events. */
|
/* Check for positive edge events. */
|
||||||
|
|
@ -46,7 +46,7 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
if (first) first = 0;
|
if (first) first = 0;
|
||||||
else fprintf(vlog_out, " or ");
|
else fprintf(vlog_out, " or ");
|
||||||
fprintf(vlog_out, "posedge ");
|
fprintf(vlog_out, "posedge ");
|
||||||
emit_name_of_nexus(scope, ivl_event_pos(event, idx));
|
emit_nexus_as_ca(scope, ivl_event_pos(event, idx), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for negative edge events. */
|
/* Check for negative edge events. */
|
||||||
|
|
@ -56,7 +56,7 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
if (first) first = 0;
|
if (first) first = 0;
|
||||||
else fprintf(vlog_out, " or ");
|
else fprintf(vlog_out, " or ");
|
||||||
fprintf(vlog_out, "negedge ");
|
fprintf(vlog_out, "negedge ");
|
||||||
emit_name_of_nexus(scope, ivl_event_neg(event, idx));
|
emit_nexus_as_ca(scope, ivl_event_neg(event, idx), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have a named event if there were no edge events. */
|
/* We have a named event if there were no edge events. */
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ static void emit_expr_array(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
{
|
{
|
||||||
char *oper = "<invalid>";
|
char *oper = "<invalid>";
|
||||||
switch(ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case '+': oper = "+"; break;
|
case '+': oper = "+"; break;
|
||||||
case '-': oper = "-"; break;
|
case '-': oper = "-"; break;
|
||||||
case '*': oper = "*"; break;
|
case '*': oper = "*"; break;
|
||||||
|
|
@ -108,7 +108,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(vlog_out, "(");
|
fprintf(vlog_out, "(");
|
||||||
switch(ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case '%':
|
case '%':
|
||||||
if (ivl_expr_value(expr) == IVL_VT_REAL) {
|
if (ivl_expr_value(expr) == IVL_VT_REAL) {
|
||||||
fprintf(stderr, "%s:%u: vlog95 error: Real modulus operator "
|
fprintf(stderr, "%s:%u: vlog95 error: Real modulus operator "
|
||||||
|
|
@ -427,6 +427,18 @@ static void emit_expr_select(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
} else {
|
} else {
|
||||||
// HERE: Should this sign extend if the expression is signed?
|
// HERE: Should this sign extend if the expression is signed?
|
||||||
emit_expr(scope, sig_expr, wid);
|
emit_expr(scope, sig_expr, wid);
|
||||||
|
/* Select part of a signal when needed. */
|
||||||
|
if ((ivl_expr_type(sig_expr) == IVL_EX_SIGNAL) &&
|
||||||
|
(ivl_expr_width(expr) < ivl_expr_width(sig_expr))) {
|
||||||
|
ivl_signal_t sig = ivl_expr_signal(sig_expr);
|
||||||
|
int msb = ivl_signal_msb(sig);
|
||||||
|
int lsb = ivl_signal_lsb(sig);
|
||||||
|
int64_t value = lsb;
|
||||||
|
unsigned e_wid = ivl_expr_width(expr) - 1;
|
||||||
|
if (msb >= lsb) value += e_wid;
|
||||||
|
else value -= e_wid;
|
||||||
|
fprintf(vlog_out, "[%"PRId64":%u]", value, lsb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,6 +520,46 @@ static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
/* A cast is a noop. */
|
/* A cast is a noop. */
|
||||||
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
break;
|
break;
|
||||||
|
case 'I':
|
||||||
|
fprintf(vlog_out, "(++");
|
||||||
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
|
fprintf(vlog_out, ")");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 sorry: Pre-increment "
|
||||||
|
"operator is not currently translated.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
fprintf(vlog_out, "(");
|
||||||
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
|
fprintf(vlog_out, "++)");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 sorry: Pre-increment "
|
||||||
|
"operator is not currently translated.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
fprintf(vlog_out, "(--");
|
||||||
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
|
fprintf(vlog_out, ")");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 sorry: Pre-decrement "
|
||||||
|
"operator is not currently translated.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
fprintf(vlog_out, "(");
|
||||||
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
|
fprintf(vlog_out, "--)");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 sorry: Pre-decrement "
|
||||||
|
"operator is not currently translated.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(vlog_out, "<unknown>");
|
fprintf(vlog_out, "<unknown>");
|
||||||
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
emit_expr(scope, ivl_expr_oper1(expr), wid);
|
||||||
|
|
@ -516,13 +568,14 @@ static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
ivl_expr_file(expr),
|
ivl_expr_file(expr),
|
||||||
ivl_expr_lineno(expr),
|
ivl_expr_lineno(expr),
|
||||||
ivl_expr_opcode(expr));
|
ivl_expr_opcode(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
{
|
{
|
||||||
switch(ivl_expr_type(expr)) {
|
switch (ivl_expr_type(expr)) {
|
||||||
case IVL_EX_ARRAY:
|
case IVL_EX_ARRAY:
|
||||||
emit_expr_array(scope, expr, wid);
|
emit_expr_array(scope, expr, wid);
|
||||||
break;
|
break;
|
||||||
|
|
@ -535,6 +588,14 @@ void emit_expr(ivl_scope_t scope, ivl_expr_t expr, unsigned wid)
|
||||||
case IVL_EX_DELAY:
|
case IVL_EX_DELAY:
|
||||||
emit_expr_delay(scope, expr, wid);
|
emit_expr_delay(scope, expr, wid);
|
||||||
break;
|
break;
|
||||||
|
case IVL_EX_ENUMTYPE:
|
||||||
|
fprintf(vlog_out, "<enum>");
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 error: Enum expressions "
|
||||||
|
"are not supported.\n",
|
||||||
|
ivl_expr_file(expr),
|
||||||
|
ivl_expr_lineno(expr));
|
||||||
|
vlog_errors += 1;
|
||||||
|
break;
|
||||||
case IVL_EX_EVENT:
|
case IVL_EX_EVENT:
|
||||||
emit_expr_event(scope, expr, wid);
|
emit_expr_event(scope, expr, wid);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -70,7 +70,7 @@ static void emit_delay(ivl_scope_t scope, ivl_expr_t expr, unsigned is_stmt)
|
||||||
ivl_signal_t sig = ivl_expr_signal(expr);
|
ivl_signal_t sig = ivl_expr_signal(expr);
|
||||||
if (ivl_signal_local(sig)) {
|
if (ivl_signal_local(sig)) {
|
||||||
assert(! is_stmt);
|
assert(! is_stmt);
|
||||||
emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0));
|
emit_nexus_as_ca(scope, ivl_signal_nex(sig, 0), 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -412,9 +412,8 @@ static unsigned find_signal_in_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
unsigned is_driver = 0;
|
unsigned is_driver = 0;
|
||||||
unsigned is_array = 0;
|
unsigned is_array = 0;
|
||||||
int64_t array_idx = 0;
|
int64_t array_idx = 0;
|
||||||
unsigned idx, count;
|
unsigned idx, count = ivl_nexus_ptrs(nex);
|
||||||
|
|
||||||
count = ivl_nexus_ptrs(nex);
|
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
||||||
ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
|
ivl_signal_t sig = ivl_nexus_ptr_sig(nex_ptr);
|
||||||
|
|
@ -501,7 +500,7 @@ static void emit_number_as_string(ivl_net_const_t net_const)
|
||||||
|
|
||||||
/* Skip any NULL bytes. */
|
/* Skip any NULL bytes. */
|
||||||
if (val == 0) continue;
|
if (val == 0) continue;
|
||||||
/* Print some values that must be escapped. */
|
/* Print some values that must be escaped. */
|
||||||
if (val == '"') fprintf(vlog_out, "\\\"");
|
if (val == '"') fprintf(vlog_out, "\\\"");
|
||||||
else if (val == '\\') fprintf(vlog_out, "\\\\");
|
else if (val == '\\') fprintf(vlog_out, "\\\\");
|
||||||
/* Print the printable characters. */
|
/* Print the printable characters. */
|
||||||
|
|
@ -616,8 +615,84 @@ static unsigned find_const_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned find_driving_signal(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
|
{
|
||||||
|
ivl_signal_t sig = 0;
|
||||||
|
unsigned is_array = 0;
|
||||||
|
int64_t array_idx = 0;
|
||||||
|
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 t_sig = ivl_nexus_ptr_sig(nex_ptr);
|
||||||
|
if (! t_sig) continue;
|
||||||
|
if (ivl_signal_local(t_sig)) continue;
|
||||||
|
/* An output can be used if it is driven by this nexus. */
|
||||||
|
if ((ivl_nexus_ptr_drive1(nex_ptr) == IVL_DR_HiZ) &&
|
||||||
|
(ivl_nexus_ptr_drive0(nex_ptr) == IVL_DR_HiZ) &&
|
||||||
|
(ivl_signal_port(t_sig) != IVL_SIP_OUTPUT)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* We have a signal that can be used to find the name. */
|
||||||
|
if (sig) {
|
||||||
|
// HERE: Which one should we use? For now it's the first one found.
|
||||||
|
// I believe this needs to be solved (see above).
|
||||||
|
fprintf(stderr, "%s:%u: vlog95 warning: Duplicate name (%s",
|
||||||
|
ivl_signal_file(t_sig), ivl_signal_lineno(t_sig),
|
||||||
|
ivl_signal_basename(t_sig));
|
||||||
|
if (ivl_signal_dimensions(t_sig) > 0) {
|
||||||
|
int64_t tmp_idx = ivl_nexus_ptr_pin(nex_ptr);
|
||||||
|
tmp_idx += ivl_signal_array_base(t_sig);
|
||||||
|
fprintf(stderr, "[%"PRId64"]", tmp_idx);
|
||||||
|
}
|
||||||
|
fprintf(stderr, ") found for nexus (%s",
|
||||||
|
ivl_signal_basename(sig));
|
||||||
|
if (is_array) fprintf(stderr, "[%"PRId64"]", array_idx);
|
||||||
|
fprintf(stderr, ")\n");
|
||||||
|
} else {
|
||||||
|
sig = t_sig;
|
||||||
|
if (ivl_signal_dimensions(sig) > 0) {
|
||||||
|
is_array = 1;
|
||||||
|
array_idx = ivl_nexus_ptr_pin(nex_ptr);
|
||||||
|
array_idx += ivl_signal_array_base(sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sig) {
|
||||||
|
emit_scope_call_path(scope, ivl_signal_scope(sig));
|
||||||
|
emit_id(ivl_signal_basename(sig));
|
||||||
|
if (is_array) fprintf(vlog_out, "[%"PRId64"]", array_idx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned is_local_input(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
|
{
|
||||||
|
ivl_signal_t sig = 0;
|
||||||
|
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 t_sig = ivl_nexus_ptr_sig(nex_ptr);
|
||||||
|
if (! t_sig) continue;
|
||||||
|
if (! ivl_signal_local(t_sig)) continue;
|
||||||
|
if (ivl_signal_port(t_sig) != IVL_SIP_INPUT) continue;
|
||||||
|
assert(! sig);
|
||||||
|
assert(ivl_signal_dimensions(t_sig) == 0);
|
||||||
|
sig = t_sig;
|
||||||
|
}
|
||||||
|
if (sig) {
|
||||||
|
fprintf(vlog_out, "ivlog%s", ivl_signal_basename(sig));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// HERE: Does this work correctly with an array reference created from @*?
|
// HERE: Does this work correctly with an array reference created from @*?
|
||||||
void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex, unsigned allow_UD)
|
||||||
{
|
{
|
||||||
ivl_scope_t mod_scope;
|
ivl_scope_t mod_scope;
|
||||||
/* First look in the local scope for the nexus name. */
|
/* First look in the local scope for the nexus name. */
|
||||||
|
|
@ -630,9 +705,16 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
if (find_signal_in_nexus(mod_scope, nex)) return;
|
if (find_signal_in_nexus(mod_scope, nex)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look to see if this is a up/down reference. */
|
||||||
|
if (allow_UD && find_driving_signal(scope, nex)) return;
|
||||||
|
|
||||||
/* If there is no signals driving this then look for a constant. */
|
/* If there is no signals driving this then look for a constant. */
|
||||||
if (find_const_nexus(scope, nex)) return;
|
if (find_const_nexus(scope, nex)) return;
|
||||||
|
|
||||||
|
/* Module inputs that are split (arg[7:4], arg[3:0]) need to use
|
||||||
|
* the local signal names. */
|
||||||
|
if (is_local_input(scope, nex)) return;
|
||||||
|
|
||||||
// HERE: Need to check arr[var]? Can this be rebuilt?
|
// HERE: Need to check arr[var]? Can this be rebuilt?
|
||||||
// Then look for down scopes and then any scope. For all this warn if
|
// Then look for down scopes and then any scope. For all this warn if
|
||||||
// multiples are found in a given scope. This all needs to be before
|
// multiples are found in a given scope. This all needs to be before
|
||||||
|
|
@ -641,7 +723,7 @@ void emit_name_of_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
/* It is possible that the nexus does not have a name. For this
|
/* It is possible that the nexus does not have a name. For this
|
||||||
* case do not print an actual name. */
|
* case do not print an actual name. */
|
||||||
fprintf(vlog_out, "/* Empty */");
|
fprintf(vlog_out, "/* Empty */");
|
||||||
dump_nexus_information(scope, nex);
|
// dump_nexus_information(scope, nex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -758,6 +840,10 @@ static unsigned is_escaped(const char *id)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Any Verilog keyword should also be escaped. */
|
||||||
|
// HERE: Create a keyword.gperf file to do this check.
|
||||||
|
if ((strcmp(id, "input") == 0) ||
|
||||||
|
(strcmp(id, "output") == 0) ) return 1;
|
||||||
/* We looked at all the digits, so this is a normal id. */
|
/* We looked at all the digits, so this is a normal id. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ static int32_t get_int32_from_bits(const char *bits, unsigned nbits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Sign extend as needed. */
|
/* Sign extend as needed. */
|
||||||
|
// HERE: Need to emit 1 instead of -1 for some of the constants.
|
||||||
|
// if (is_signed && (nbits > 1) && (msb == '1') && (trim_wid < 32U)) {
|
||||||
if (is_signed && (msb == '1') && (trim_wid < 32U)) {
|
if (is_signed && (msb == '1') && (trim_wid < 32U)) {
|
||||||
value |= ~(((int32_t)1 << trim_wid) - (int32_t)1);
|
value |= ~(((int32_t)1 << trim_wid) - (int32_t)1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ void emit_net_def(ivl_scope_t scope, ivl_signal_t sig)
|
||||||
ivl_signal_lineno(sig), ivl_signal_basename(sig));
|
ivl_signal_lineno(sig), ivl_signal_basename(sig));
|
||||||
vlog_errors += 1;
|
vlog_errors += 1;
|
||||||
} else {
|
} else {
|
||||||
switch(ivl_signal_type(sig)) {
|
switch (ivl_signal_type(sig)) {
|
||||||
case IVL_SIT_TRI:
|
case IVL_SIT_TRI:
|
||||||
case IVL_SIT_UWIRE:
|
case IVL_SIT_UWIRE:
|
||||||
// HERE: Need to add support for supply nets. Probably supply strength
|
// HERE: Need to add support for supply nets. Probably supply strength
|
||||||
|
|
@ -363,19 +363,21 @@ static void emit_module_ports(ivl_scope_t scope)
|
||||||
if (count == 0) return;
|
if (count == 0) return;
|
||||||
|
|
||||||
fprintf(vlog_out, "(");
|
fprintf(vlog_out, "(");
|
||||||
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, 0));
|
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, 0), 0);
|
||||||
for (idx = 1; idx < count; idx += 1) {
|
for (idx = 1; idx < count; idx += 1) {
|
||||||
fprintf(vlog_out, ", ");
|
fprintf(vlog_out, ", ");
|
||||||
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, idx));
|
emit_nexus_as_ca(scope, ivl_scope_mod_port(scope, idx), 0);
|
||||||
}
|
}
|
||||||
fprintf(vlog_out, ")");
|
fprintf(vlog_out, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ivl_signal_t get_port_from_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
static ivl_signal_t get_port_from_nexus(ivl_scope_t scope, ivl_nexus_t nex,
|
||||||
|
unsigned *word)
|
||||||
{
|
{
|
||||||
assert(nex);
|
assert(nex);
|
||||||
unsigned idx, count = ivl_nexus_ptrs(nex);
|
unsigned idx, count = ivl_nexus_ptrs(nex);
|
||||||
ivl_signal_t sig = 0;
|
ivl_signal_t sig = 0;
|
||||||
|
*word = 0;
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
||||||
ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
|
ivl_signal_t t_sig = ivl_nexus_ptr_sig(nex_ptr);
|
||||||
|
|
@ -383,6 +385,7 @@ static ivl_signal_t get_port_from_nexus(ivl_scope_t scope, ivl_nexus_t nex)
|
||||||
if (ivl_signal_scope(t_sig) != scope) continue;
|
if (ivl_signal_scope(t_sig) != scope) continue;
|
||||||
assert(! sig);
|
assert(! sig);
|
||||||
sig = t_sig;
|
sig = t_sig;
|
||||||
|
*word = ivl_nexus_ptr_pin(nex_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sig;
|
return sig;
|
||||||
|
|
@ -475,7 +478,12 @@ static void emit_port(ivl_signal_t port)
|
||||||
}
|
}
|
||||||
emit_sig_type(port);
|
emit_sig_type(port);
|
||||||
fprintf(vlog_out, " ");
|
fprintf(vlog_out, " ");
|
||||||
|
/* Split port (arg[7:4],arg[3:0]) are generated using local signals. */
|
||||||
|
if (ivl_signal_local(port)) {
|
||||||
|
fprintf(vlog_out, "ivlog%s", ivl_signal_basename(port));
|
||||||
|
} else {
|
||||||
emit_id(ivl_signal_basename(port));
|
emit_id(ivl_signal_basename(port));
|
||||||
|
}
|
||||||
fprintf(vlog_out, ";");
|
fprintf(vlog_out, ";");
|
||||||
emit_sig_file_line(port);
|
emit_sig_file_line(port);
|
||||||
fprintf(vlog_out, "\n");
|
fprintf(vlog_out, "\n");
|
||||||
|
|
@ -483,10 +491,11 @@ static void emit_port(ivl_signal_t port)
|
||||||
|
|
||||||
static void emit_module_port_defs(ivl_scope_t scope)
|
static void emit_module_port_defs(ivl_scope_t scope)
|
||||||
{
|
{
|
||||||
unsigned idx, count = ivl_scope_ports(scope);
|
unsigned word, idx, count = ivl_scope_ports(scope);
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
|
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
|
||||||
ivl_signal_t port = get_port_from_nexus(scope, nex);
|
ivl_signal_t port = get_port_from_nexus(scope, nex, &word);
|
||||||
|
// HERE: Do we need to use word?
|
||||||
if (port) emit_port(port);
|
if (port) emit_port(port);
|
||||||
else {
|
else {
|
||||||
fprintf(vlog_out, "<missing>");
|
fprintf(vlog_out, "<missing>");
|
||||||
|
|
@ -502,15 +511,17 @@ static void emit_module_port_defs(ivl_scope_t scope)
|
||||||
|
|
||||||
static void emit_module_call_expr(ivl_scope_t scope, unsigned idx)
|
static void emit_module_call_expr(ivl_scope_t scope, unsigned idx)
|
||||||
{
|
{
|
||||||
|
unsigned word;
|
||||||
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
|
ivl_nexus_t nex = ivl_scope_mod_port(scope, idx);
|
||||||
ivl_signal_t port = get_port_from_nexus(scope, nex);
|
ivl_signal_t port = get_port_from_nexus(scope, nex, &word);
|
||||||
/* For an input port we need to emit the driving expression. */
|
/* For an input port we need to emit the driving expression. */
|
||||||
if (ivl_signal_port(port) == IVL_SIP_INPUT) {
|
if (ivl_signal_port(port) == IVL_SIP_INPUT) {
|
||||||
emit_nexus_port_driver_as_ca(ivl_scope_parent(scope),
|
emit_nexus_port_driver_as_ca(ivl_scope_parent(scope),
|
||||||
ivl_signal_nex(port, 0));
|
ivl_signal_nex(port, word));
|
||||||
/* For an output we need to emit the signal the output is driving. */
|
/* For an output we need to emit the signal the output is driving. */
|
||||||
} else {
|
} else {
|
||||||
emit_nexus_as_ca(ivl_scope_parent(scope), ivl_signal_nex(port, 0));
|
emit_nexus_as_ca(ivl_scope_parent(scope),
|
||||||
|
ivl_signal_nex(port, word), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -536,6 +547,70 @@ static void emit_task_func_port_defs(ivl_scope_t scope)
|
||||||
if (count) fprintf(vlog_out, "\n");
|
if (count) fprintf(vlog_out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at all the processes to see if we can find one with the expected
|
||||||
|
* scope. If we don't find one then we can assume the block only has
|
||||||
|
* variable definitions and needs to be emitted here in the scope code.
|
||||||
|
*/
|
||||||
|
static int no_stmts_in_process(ivl_process_t proc, ivl_scope_t scope)
|
||||||
|
{
|
||||||
|
ivl_statement_t stmt = ivl_process_stmt(proc);
|
||||||
|
switch (ivl_statement_type(stmt)) {
|
||||||
|
case IVL_ST_BLOCK:
|
||||||
|
case IVL_ST_FORK:
|
||||||
|
if (ivl_stmt_block_scope(stmt) == scope) return 1;
|
||||||
|
default: /* Do nothing. */ ;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a named block has no statements then we may need to emit it here if
|
||||||
|
* there are variable definitions in the scope. We translate all this to
|
||||||
|
* an initial and named begin since that is enough to hold the variables.
|
||||||
|
*/
|
||||||
|
static void emit_named_block_scope(ivl_scope_t scope)
|
||||||
|
{
|
||||||
|
unsigned idx, count = ivl_scope_events(scope);
|
||||||
|
unsigned named_ev = 0;
|
||||||
|
|
||||||
|
/* If there are no parameters, signals or named events then skip
|
||||||
|
* this block. */
|
||||||
|
for (idx = 0; idx < count; idx += 1) {
|
||||||
|
ivl_event_t event = ivl_scope_event(scope, idx);
|
||||||
|
/* If this event has any type of edge sensitivity then it is
|
||||||
|
* not a named event. */
|
||||||
|
if (ivl_event_nany(event)) continue;
|
||||||
|
if (ivl_event_npos(event)) continue;
|
||||||
|
if (ivl_event_nneg(event)) continue;
|
||||||
|
named_ev = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((ivl_scope_params(scope) == 0) && (ivl_scope_sigs(scope) == 0) &&
|
||||||
|
(named_ev == 0)) return;
|
||||||
|
/* Currently we only need to emit a named block for the variables
|
||||||
|
* if the parent scope is a module. This gets much more complicated
|
||||||
|
* if this is not true. */
|
||||||
|
if (ivl_scope_type(ivl_scope_parent(scope)) != IVL_SCT_MODULE) return;
|
||||||
|
/* Scan all the processes looking for one that matches this scope.
|
||||||
|
* If a match is found then this named block was already emitted by
|
||||||
|
* the process code. */
|
||||||
|
if (ivl_design_process(design, (ivl_process_f)no_stmts_in_process,
|
||||||
|
scope)) return;
|
||||||
|
/* A match was not found so emit the named block here to get the
|
||||||
|
* variable definitions. */
|
||||||
|
fprintf(vlog_out, "\n%*cinitial begin: ", indent, ' ');
|
||||||
|
emit_id(ivl_scope_tname(scope));
|
||||||
|
emit_scope_file_line(scope);
|
||||||
|
fprintf(vlog_out, "\n");
|
||||||
|
indent += indent_incr;
|
||||||
|
emit_scope_variables(scope);
|
||||||
|
indent -= indent_incr;
|
||||||
|
fprintf(vlog_out, "%*cend /* ", indent, ' ');
|
||||||
|
emit_id(ivl_scope_tname(scope));
|
||||||
|
fprintf(vlog_out, " */\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This search method may be slow for a large structural design with a
|
* This search method may be slow for a large structural design with a
|
||||||
* large number of gate types. That's not what this converter was built
|
* large number of gate types. That's not what this converter was built
|
||||||
|
|
@ -652,6 +727,7 @@ int emit_scope(ivl_scope_t scope, ivl_scope_t parent)
|
||||||
case IVL_SCT_BEGIN:
|
case IVL_SCT_BEGIN:
|
||||||
case IVL_SCT_FORK:
|
case IVL_SCT_FORK:
|
||||||
assert(indent != 0);
|
assert(indent != 0);
|
||||||
|
emit_named_block_scope(scope);
|
||||||
return 0; /* A named begin/fork is handled in line. */
|
return 0; /* A named begin/fork is handled in line. */
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s:%u: vlog95 error: Unsupported scope type "
|
fprintf(stderr, "%s:%u: vlog95 error: Unsupported scope type "
|
||||||
|
|
|
||||||
|
|
@ -780,7 +780,7 @@ static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
{
|
{
|
||||||
char *case_type;
|
char *case_type;
|
||||||
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
|
unsigned idx, default_case, count = ivl_stmt_case_count(stmt);
|
||||||
switch(ivl_statement_type(stmt)) {
|
switch (ivl_statement_type(stmt)) {
|
||||||
case IVL_ST_CASE:
|
case IVL_ST_CASE:
|
||||||
case IVL_ST_CASER:
|
case IVL_ST_CASER:
|
||||||
case_type = "case";
|
case_type = "case";
|
||||||
|
|
@ -1047,7 +1047,7 @@ static void emit_stmt_while(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
|
|
||||||
void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
|
void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
{
|
{
|
||||||
switch(ivl_statement_type(stmt)) {
|
switch (ivl_statement_type(stmt)) {
|
||||||
case IVL_ST_NOOP:
|
case IVL_ST_NOOP:
|
||||||
/* If this is a statement termination then just finish the
|
/* If this is a statement termination then just finish the
|
||||||
* statement, otherwise print an empty begin/end pair. */
|
* statement, otherwise print an empty begin/end pair. */
|
||||||
|
|
@ -1159,7 +1159,8 @@ void emit_stmt(ivl_scope_t scope, ivl_statement_t stmt)
|
||||||
|
|
||||||
void emit_process(ivl_scope_t scope, ivl_process_t proc)
|
void emit_process(ivl_scope_t scope, ivl_process_t proc)
|
||||||
{
|
{
|
||||||
ivl_statement_t stmt;
|
ivl_statement_t stmt = ivl_process_stmt(proc);
|
||||||
|
if (ivl_statement_type(stmt) == IVL_ST_NOOP) return;
|
||||||
fprintf(vlog_out, "\n%*c", get_indent(), ' ');
|
fprintf(vlog_out, "\n%*c", get_indent(), ' ');
|
||||||
switch (ivl_process_type(proc)) {
|
switch (ivl_process_type(proc)) {
|
||||||
case IVL_PR_INITIAL:
|
case IVL_PR_INITIAL:
|
||||||
|
|
@ -1181,7 +1182,6 @@ void emit_process(ivl_scope_t scope, ivl_process_t proc)
|
||||||
ivl_process_file(proc),
|
ivl_process_file(proc),
|
||||||
ivl_process_lineno(proc));
|
ivl_process_lineno(proc));
|
||||||
}
|
}
|
||||||
stmt = ivl_process_stmt(proc);
|
|
||||||
if (ivl_statement_type(stmt) == IVL_ST_NOOP) {
|
if (ivl_statement_type(stmt) == IVL_ST_NOOP) {
|
||||||
fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' ');
|
fprintf(vlog_out, " begin\n%*cend\n", get_indent(), ' ');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
static void emit_entry(ivl_udp_t udp, char entry, unsigned *rerun)
|
static void emit_entry(ivl_udp_t udp, char entry, unsigned *rerun)
|
||||||
{
|
{
|
||||||
const char *value = 0;
|
const char *value = 0;
|
||||||
switch(entry) {
|
switch (entry) {
|
||||||
case '0':
|
case '0':
|
||||||
value = " 0 ";
|
value = " 0 ";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2011 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2012 Cary R. (cygcary@yahoo.com)
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
static const char*version_string =
|
static const char*version_string =
|
||||||
"Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
"Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||||
"Copyright (C) 2010-2011 Cary R. (cygcary@yahoo.com)\n\n"
|
"Copyright (C) 2010-2012 Cary R. (cygcary@yahoo.com)\n\n"
|
||||||
" This program is free software; you can redistribute it and/or modify\n"
|
" This program is free software; you can redistribute it and/or modify\n"
|
||||||
" it under the terms of the GNU General Public License as published by\n"
|
" it under the terms of the GNU General Public License as published by\n"
|
||||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||||
|
|
@ -195,6 +195,10 @@ int target_design(ivl_design_t des)
|
||||||
|
|
||||||
fclose(vlog_out);
|
fclose(vlog_out);
|
||||||
|
|
||||||
|
/* A do nothing call to prevent warnings about this routine not
|
||||||
|
* being used. */
|
||||||
|
dump_nexus_information(0, 0);
|
||||||
|
|
||||||
return vlog_errors;
|
return vlog_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,10 @@ extern void emit_scope_path(ivl_scope_t scope, ivl_scope_t call_scope);
|
||||||
extern void emit_scope_variables(ivl_scope_t scope);
|
extern void emit_scope_variables(ivl_scope_t scope);
|
||||||
extern void emit_scope_call_path(ivl_scope_t scope, ivl_scope_t call_scope);
|
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_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_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);
|
unsigned allow_UD);
|
||||||
|
extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex,
|
||||||
|
unsigned allow_UD);
|
||||||
extern void emit_nexus_port_driver_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_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_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue