Connect signals together if joined in a nexus

This commit is contained in:
Nick Gasson 2008-07-29 21:03:00 +01:00
parent eaf1cc9120
commit 9a5b7bb0b0
1 changed files with 55 additions and 37 deletions

View File

@ -45,12 +45,14 @@ void set_active_entity(vhdl_entity *ent)
* a VHDL scope. If that nexus portion does not contain a signal,
* then `tmpname' gives the name of the temporary that will be
* used when this nexus is used in `scope' (e.g. for LPMs that
* appear in instantiations).
* appear in instantiations). The list `connect' lists all the
* signals that should be joined together to re-create the net.
*/
struct scope_nexus_t {
vhdl_scope *scope;
ivl_signal_t sig; // A real signal
string tmpname; // A new temporary signal
ivl_signal_t sig; // A real signal
string tmpname; // A new temporary signal
list<ivl_signal_t> connect; // Other signals to wire together
};
/*
@ -65,26 +67,6 @@ struct nexus_private_t {
vhdl_expr *const_driver;
};
/*
* Remember that sig is the representative of this nexus in scope.
*/
static void link_scope_to_nexus_signal(nexus_private_t *priv, vhdl_scope *scope,
ivl_signal_t sig)
{
scope_nexus_t sigmap = { scope, sig, "" };
priv->signals.push_back(sigmap);
}
/*
* Make a temporary the representative of this nexus in scope.
*/
static void link_scope_to_nexus_tmp(nexus_private_t *priv, vhdl_scope *scope,
const string &name)
{
scope_nexus_t sigmap = { scope, NULL, name };
priv->signals.push_back(sigmap);
}
/*
* Returns the scope_nexus_t of this nexus visible within scope.
*/
@ -98,6 +80,38 @@ static scope_nexus_t *visible_nexus(nexus_private_t *priv, vhdl_scope *scope)
return NULL;
}
/*
* Remember that a signal in `scope' is part of this nexus. The
* first signal passed to this function for a scope will be used
* as the canonical representation of this nexus when we need to
* convert it to a variable reference (e.g. in a LPM input/output).
*/
static void link_scope_to_nexus_signal(nexus_private_t *priv, vhdl_scope *scope,
ivl_signal_t sig)
{
scope_nexus_t *sn;
if ((sn = visible_nexus(priv, scope))) {
assert(sn->tmpname == "");
cout << "need to tie up " << get_renamed_signal(sig) << endl;
sn->connect.push_back(sig);
}
else {
scope_nexus_t new_sn = { scope, sig, "" };
priv->signals.push_back(new_sn);
}
}
/*
* Make a temporary the representative of this nexus in scope.
*/
static void link_scope_to_nexus_tmp(nexus_private_t *priv, vhdl_scope *scope,
const string &name)
{
scope_nexus_t new_sn = { scope, NULL, name };
priv->signals.push_back(new_sn);
}
/*
* Finds the name of the nexus signal within this scope.
*/
@ -128,16 +142,7 @@ void draw_nexus(ivl_nexus_t nexus)
cout << "signal " << ivl_signal_basename(sig) << endl;
vhdl_scope *scope = find_scope_for_signal(sig);
if (visible_nexus(priv, scope)) {
cout << "...should be linked to "
<< visible_nexus_signal_name(priv, scope) << endl;
assert(false);
}
else {
cout << "...represents this nexus in scope " << hex << scope << endl;
link_scope_to_nexus_signal(priv, scope, sig);
}
link_scope_to_nexus_signal(priv, scope, sig);
}
}
@ -637,7 +642,7 @@ static int draw_function(ivl_scope_t scope, ivl_scope_t parent)
vhdl_type::type_for(ivl_signal_width(sig),
ivl_signal_signed(sig) != 0);
std::string signame = make_safe_name(sig);
string signame(make_safe_name(sig));
switch (ivl_signal_port(sig)) {
case IVL_SIP_INPUT:
@ -773,19 +778,32 @@ static int draw_constant_drivers(ivl_scope_t scope, void *_parent)
static_cast<nexus_private_t*>(ivl_nexus_get_private(nex));
assert(priv);
vhdl_scope *arch_scope = ent->get_arch()->get_scope();
if (priv->const_driver) {
assert(i == 0); // TODO: Make work for more words
cout << "NEEDS CONST DRIVER!" << endl;
cout << "(in scope " << ivl_scope_name(scope) << endl;
vhdl_var_ref *ref =
nexus_to_var_ref(ent->get_arch()->get_scope(), nex);
vhdl_var_ref *ref = nexus_to_var_ref(arch_scope, nex);
ent->get_arch()->add_stmt
(new vhdl_cassign_stmt(ref, priv->const_driver));
priv->const_driver = NULL;
}
scope_nexus_t *sn = visible_nexus(priv, arch_scope);
for (list<ivl_signal_t>::const_iterator it = sn->connect.begin();
it != sn->connect.end();
++it) {
vhdl_var_ref *rref =
new vhdl_var_ref(get_renamed_signal(sn->sig).c_str(), NULL);
vhdl_var_ref *lref =
new vhdl_var_ref(get_renamed_signal(*it).c_str(), NULL);
ent->get_arch()->add_stmt(new vhdl_cassign_stmt(lref, rref));
}
sn->connect.clear();
}
}
}