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:
parent
1fbe777c81
commit
e375b26f78
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, ' ');
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue