Refactor nexus expansion functions.

Now a single function nexus_to_expr
This commit is contained in:
Nick Gasson 2008-07-13 15:17:14 +01:00
parent 27a40cfdcd
commit 6af201ea03
2 changed files with 56 additions and 60 deletions

View File

@ -29,40 +29,24 @@ static vhdl_expr *translate_logic(vhdl_scope *scope, ivl_net_logic_t log);
static std::string make_safe_name(ivl_signal_t sig);
/*
* Given a nexus find a constant value in it that can be used
* as an initial signal value.
* The types of VHDL object a nexus can be converted into.
*/
static vhdl_expr *nexus_to_const(ivl_nexus_t nexus)
{
int nptrs = ivl_nexus_ptrs(nexus);
for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
ivl_net_const_t con;
if ((con = ivl_nexus_ptr_con(nexus_ptr))) {
if (ivl_const_width(con) == 1)
return new vhdl_const_bit(ivl_const_bits(con)[0]);
else
return new vhdl_const_bits
(ivl_const_bits(con), ivl_const_width(con),
ivl_const_signed(con) != 0);
}
else {
// Ignore other types of nexus pointer
}
}
return NULL;
}
enum vhdl_nexus_obj_t {
NEXUS_TO_VAR_REF = 1<<0,
NEXUS_TO_CONST = 1<<1,
NEXUS_TO_OTHER = 1<<2,
};
#define NEXUS_TO_ANY \
NEXUS_TO_VAR_REF | NEXUS_TO_CONST | NEXUS_TO_OTHER
/*
* Given a nexus and an architecture scope, find the first signal
* that is connected to the nexus, if there is one. Never return
* a reference to 'ignore' if it is found in the nexus.
* Given a nexus, generate a VHDL expression object to represent it.
* The allowed VHDL expression types are given by vhdl_nexus_obj_t.
*/
static vhdl_expr *nexus_to_expr(vhdl_scope *arch_scope, ivl_nexus_t nexus,
int allowed = NEXUS_TO_ANY,
ivl_signal_t ignore = NULL)
{
{
int nptrs = ivl_nexus_ptrs(nexus);
for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
@ -70,7 +54,10 @@ static vhdl_expr *nexus_to_expr(vhdl_scope *arch_scope, ivl_nexus_t nexus,
ivl_signal_t sig;
ivl_net_logic_t log;
ivl_lpm_t lpm;
if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
ivl_net_const_t con;
ivl_switch_t sw;
if ((allowed & NEXUS_TO_VAR_REF) &&
(sig = ivl_nexus_ptr_sig(nexus_ptr))) {
if (!seen_signal_before(sig) || sig == ignore)
continue;
@ -83,41 +70,28 @@ static vhdl_expr *nexus_to_expr(vhdl_scope *arch_scope, ivl_nexus_t nexus,
vhdl_type *type = new vhdl_type(*(decl->get_type()));
return new vhdl_var_ref(signame, type);
}
else if ((log = ivl_nexus_ptr_log(nexus_ptr))) {
else if ((allowed & NEXUS_TO_OTHER) &&
(log = ivl_nexus_ptr_log(nexus_ptr))) {
return translate_logic(arch_scope, log);
}
else if ((lpm = ivl_nexus_ptr_lpm(nexus_ptr))) {
else if ((allowed & NEXUS_TO_OTHER) &&
(lpm = ivl_nexus_ptr_lpm(nexus_ptr))) {
vhdl_expr *e = lpm_to_expr(arch_scope, lpm);
if (e)
return e;
}
else {
// Ignore other types of nexus pointer
else if ((allowed & NEXUS_TO_CONST) &&
(con = ivl_nexus_ptr_con(nexus_ptr))) {
if (ivl_const_width(con) == 1)
return new vhdl_const_bit(ivl_const_bits(con)[0]);
else
return new vhdl_const_bits
(ivl_const_bits(con), ivl_const_width(con),
ivl_const_signed(con) != 0);
}
}
assert(false);
}
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus)
{
int nptrs = ivl_nexus_ptrs(nexus);
for (int i = 0; i < nptrs; i++) {
ivl_nexus_ptr_t nexus_ptr = ivl_nexus_ptr(nexus, i);
ivl_signal_t sig;
if ((sig = ivl_nexus_ptr_sig(nexus_ptr))) {
if (!seen_signal_before(sig))
continue;
const char *signame = get_renamed_signal(sig).c_str();
vhdl_decl *decl = arch_scope->get_decl(signame);
if (NULL == decl)
continue; // Not in this scope
vhdl_type *type = new vhdl_type(*(decl->get_type()));
return new vhdl_var_ref(signame, type);
else if ((allowed & NEXUS_TO_OTHER) &&
(sw = ivl_nexus_ptr_switch(nexus_ptr))) {
assert(false);
}
else {
// Ignore other types of nexus pointer
@ -127,6 +101,17 @@ vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus)
return NULL;
}
/*
* Guarantees the result will never be NULL.
*/
vhdl_var_ref *nexus_to_var_ref(vhdl_scope *arch_scope, ivl_nexus_t nexus)
{
vhdl_var_ref *ref = dynamic_cast<vhdl_var_ref*>
(nexus_to_expr(arch_scope, nexus, NEXUS_TO_VAR_REF));
assert(ref);
return ref;
}
/*
* Convert the inputs of a logic gate to a binary expression.
*/
@ -266,7 +251,9 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
// A local signal can have a constant initializer in VHDL
// This may be found in the signal's nexus
// TODO: Make this work for multiple words
vhdl_expr *init = nexus_to_const(ivl_signal_nex(sig, 0));
vhdl_expr *init =
nexus_to_expr(ent->get_scope(), ivl_signal_nex(sig, 0),
NEXUS_TO_CONST);
if (init != NULL)
decl->set_initial(init);
@ -285,7 +272,9 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope)
// Check for constant values
// For outputs these must be continuous assigns of
// the constant to the port
vhdl_expr *init = nexus_to_const(ivl_signal_nex(sig, 0));
vhdl_expr *init =
nexus_to_expr(ent->get_scope(), ivl_signal_nex(sig, 0),
NEXUS_TO_CONST);
if (init != NULL) {
vhdl_var_ref *ref = new vhdl_var_ref(name.c_str(), NULL);
ent->get_arch()->add_stmt(new vhdl_cassign_stmt(ref, init));
@ -390,7 +379,8 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
// TODO: Work for multiple words
ivl_nexus_t nexus = ivl_signal_nex(to, 0);
vhdl_expr *to_e = nexus_to_expr(parent->get_arch()->get_scope(), nexus, to);
vhdl_expr *to_e = nexus_to_expr(parent->get_arch()->get_scope(),
nexus, NEXUS_TO_ANY, to);
assert(to_e);
// The expressions in a VHDL port map must be 'globally static'

View File

@ -15,6 +15,7 @@ package Verilog_Support is
-- Routines to implement Verilog reduction operators
function Reduce_OR(X : unsigned) return std_logic;
function Reduce_Or(X : std_logic) return std_logic;
-- Convert Boolean to std_logic
function Active_High(B : Boolean) return std_logic;
@ -40,6 +41,11 @@ package body Verilog_Support is
return '0';
end function;
function Reduce_OR(X : std_logic) return std_logic is
begin
return X;
end function;
function Active_High(B : Boolean) return std_logic is
begin
if B then