tgt-vlog95: fix mixed-scope multiple constant assignments to a net (issue #1181)
The vlog95 code generator collects all the constant assignments to a net within each scope and then emits them. The old code only recorded the ivl_signal_t for each constant assignment, which meant it had to iterate through the nexus pointers in the assicated nexus to find the constant. When there were multiple constant assignments to the same net, it needed to record which assignments had already been emitted, which it did by keeping a count in the nexus private data and skipping that many constants on each successive assignment. However the count did not get reset after emitting all the assignments in that scope, so if there were assignments to the same net made in another scope, the count would already be positive and those assignments would also be skipped. This could probably have been fixed by clearing the nexus private data after processing the constant assignment list for each scope, but it is more efficient to record the ivl_nexus_ptr_t for each constant along with the ivl_signal_t, eliminating the need to search for the associated nexus pointer.
This commit is contained in:
parent
96d28250bd
commit
2817bf59c5
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2022 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2011-2024 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
|
||||||
|
|
@ -2275,46 +2275,28 @@ void emit_tran(ivl_scope_t scope, ivl_switch_t tran)
|
||||||
fprintf(vlog_out, "\n");
|
fprintf(vlog_out, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig)
|
void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig,
|
||||||
|
ivl_nexus_ptr_t nex_ptr)
|
||||||
{
|
{
|
||||||
ivl_nexus_t nex = ivl_signal_nex(sig, 0);
|
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
||||||
unsigned idx, count = ivl_nexus_ptrs(nex);
|
assert(net_const);
|
||||||
unsigned long emitted = (uintptr_t) ivl_nexus_get_private(nex);
|
fprintf(vlog_out, "%*cassign", indent, ' ');
|
||||||
for (idx = 0; idx < count; idx += 1) {
|
emit_strength(ivl_nexus_ptr_drive1(nex_ptr),
|
||||||
ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx);
|
ivl_nexus_ptr_drive0(nex_ptr),
|
||||||
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
2, "assign",
|
||||||
if (! net_const) continue;
|
ivl_signal_file(sig), ivl_signal_lineno(sig));
|
||||||
if (scope != ivl_const_scope(net_const)) continue;
|
emit_delay(scope,
|
||||||
/* Found the constant so emit it if it has not been emitted. */
|
ivl_const_delay(net_const, 0),
|
||||||
if (emitted) {
|
ivl_const_delay(net_const, 1),
|
||||||
--emitted;
|
ivl_const_delay(net_const, 2),
|
||||||
continue;
|
3);
|
||||||
}
|
fprintf(vlog_out, " ");
|
||||||
fprintf(vlog_out, "%*cassign", indent, ' ');
|
emit_id(ivl_signal_basename(sig));
|
||||||
emit_strength(ivl_nexus_ptr_drive1(nex_ptr),
|
fprintf(vlog_out, " = ");
|
||||||
ivl_nexus_ptr_drive0(nex_ptr),
|
emit_const_nexus(scope, net_const);
|
||||||
2, "assign",
|
fprintf(vlog_out, ";");
|
||||||
ivl_signal_file(sig), ivl_signal_lineno(sig));
|
emit_sig_file_line(sig);
|
||||||
emit_delay(scope,
|
fprintf(vlog_out, "\n");
|
||||||
ivl_const_delay(net_const, 0),
|
|
||||||
ivl_const_delay(net_const, 1),
|
|
||||||
ivl_const_delay(net_const, 2),
|
|
||||||
3);
|
|
||||||
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);
|
|
||||||
fprintf(vlog_out, "\n");
|
|
||||||
/* Increment the emitted constant count by one. */
|
|
||||||
ivl_nexus_set_private(nex,
|
|
||||||
(void *) ((uintptr_t) ivl_nexus_get_private(nex) + 1U));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* We must find the constant in the nexus. */
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_drive(ivl_drive_t drive)
|
static void dump_drive(ivl_drive_t drive)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2022 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2024 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
|
||||||
|
|
@ -161,21 +161,28 @@ static void emit_var_def(ivl_signal_t sig)
|
||||||
* Keep a list of constants that drive nets and need to be emitted as
|
* Keep a list of constants that drive nets and need to be emitted as
|
||||||
* a continuous assignment.
|
* a continuous assignment.
|
||||||
*/
|
*/
|
||||||
static ivl_signal_t *net_consts = 0;
|
typedef struct {
|
||||||
|
ivl_signal_t sig;
|
||||||
|
ivl_nexus_ptr_t nex_ptr;
|
||||||
|
} net_const_t;
|
||||||
|
|
||||||
|
static net_const_t *net_consts = 0;
|
||||||
static unsigned num_net_consts = 0;
|
static unsigned num_net_consts = 0;
|
||||||
|
|
||||||
static void add_net_const_to_list(ivl_signal_t net_const)
|
static void add_net_const_to_list(ivl_signal_t sig, ivl_nexus_ptr_t nex_ptr)
|
||||||
{
|
{
|
||||||
num_net_consts += 1;
|
num_net_consts += 1;
|
||||||
net_consts = realloc(net_consts, num_net_consts * sizeof(ivl_signal_t));
|
net_consts = realloc(net_consts, num_net_consts * sizeof(net_const_t));
|
||||||
net_consts[num_net_consts-1] = net_const;
|
net_consts[num_net_consts-1].sig = sig;
|
||||||
|
net_consts[num_net_consts-1].nex_ptr = nex_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned emit_and_free_net_const_list(ivl_scope_t scope)
|
static unsigned emit_and_free_net_const_list(ivl_scope_t scope)
|
||||||
{
|
{
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
for (idx = 0; idx < num_net_consts; idx += 1) {
|
for (idx = 0; idx < num_net_consts; idx += 1) {
|
||||||
emit_signal_net_const_as_ca(scope, net_consts[idx]);
|
emit_signal_net_const_as_ca(scope, net_consts[idx].sig,
|
||||||
|
net_consts[idx].nex_ptr);
|
||||||
}
|
}
|
||||||
free(net_consts);
|
free(net_consts);
|
||||||
net_consts = 0;
|
net_consts = 0;
|
||||||
|
|
@ -193,7 +200,7 @@ static void save_net_constants(const ivl_scope_t scope, ivl_signal_t sig)
|
||||||
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr);
|
||||||
if (! net_const) continue;
|
if (! net_const) continue;
|
||||||
if (scope != ivl_const_scope(net_const)) continue;
|
if (scope != ivl_const_scope(net_const)) continue;
|
||||||
add_net_const_to_list(sig);
|
add_net_const_to_list(sig, nex_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_vlog95_priv_H
|
#ifndef IVL_vlog95_priv_H
|
||||||
#define IVL_vlog95_priv_H
|
#define IVL_vlog95_priv_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2019 Cary R. (cygcary@yahoo.com)
|
* Copyright (C) 2010-2024 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
|
||||||
|
|
@ -105,7 +105,8 @@ extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex,
|
||||||
unsigned allow_UD, unsigned sign_extend);
|
unsigned allow_UD, unsigned sign_extend);
|
||||||
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,
|
||||||
|
ivl_nexus_ptr_t nex_ptr);
|
||||||
|
|
||||||
extern void add_udp_to_list(ivl_udp_t udp);
|
extern void add_udp_to_list(ivl_udp_t udp);
|
||||||
extern void emit_udp_list(void);
|
extern void emit_udp_list(void);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue