Fix VHDL bug where constant is assigned to input

This fixes a bug where the VHDL target would not
map ports in cases where the port was driven by
a constant.
This commit is contained in:
Nick Gasson 2009-01-28 10:09:27 +00:00 committed by Stephen Williams
parent babc9c1352
commit 3dadedf9b5
3 changed files with 42 additions and 32 deletions

View File

@ -589,39 +589,49 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent,
nexus_private_t *priv = nexus_private_t *priv =
static_cast<nexus_private_t*>(ivl_nexus_get_private(nexus)); static_cast<nexus_private_t*>(ivl_nexus_get_private(nexus));
assert(priv); assert(priv);
if (!visible_nexus(priv, arch_scope)) {
vhdl_expr *map_to = NULL;
const string name(make_safe_name(to));
// We can only map ports to signals or constants
if (visible_nexus(priv, arch_scope)) {
vhdl_var_ref *ref = nexus_to_var_ref(parent->get_arch()->get_scope(), nexus);
// If we're mapping an output of this entity to an output of
// the child entity, then VHDL will not let us read the value
// of the signal (i.e. it must pass straight through).
// However, Verilog allows the signal to be read in the parent.
// The solution used here is to create an intermediate signal
// and connect it to both ports.
vhdl_decl* from_decl =
parent->get_arch()->get_scope()->get_decl(ref->get_name());
if (!from_decl->is_readable()
&& !arch_scope->have_declared(name + "_Readable")) {
vhdl_decl* tmp_decl =
new vhdl_signal_decl(name + "_Readable", ref->get_type());
// Add a comment to explain what this is for
tmp_decl->set_comment("Needed to connect outputs");
arch_scope->add_decl(tmp_decl);
parent->get_arch()->add_stmt
(new vhdl_cassign_stmt(from_decl->make_ref(), tmp_decl->make_ref()));
map_to = tmp_decl->make_ref();
}
else
map_to = ref;
}
else if (priv->const_driver && ivl_signal_port(to) == IVL_SIP_INPUT) {
map_to = priv->const_driver;
priv->const_driver = NULL;
}
else {
// This nexus isn't attached to anything in the parent // This nexus isn't attached to anything in the parent
return; return;
} }
vhdl_var_ref *ref = nexus_to_var_ref(parent->get_arch()->get_scope(), nexus); inst->map_port(name, map_to);
string name = make_safe_name(to);
// If we're mapping an output of this entity to an output of
// the child entity, then VHDL will not let us read the value
// of the signal (i.e. it must pass straight through).
// However, Verilog allows the signal to be read in the parent.
// The solution used here is to create an intermediate signal
// and connect it to both ports.
vhdl_decl* from_decl =
parent->get_arch()->get_scope()->get_decl(ref->get_name());
if (!from_decl->is_readable()
&& !arch_scope->have_declared(name + "_Readable")) {
vhdl_decl* tmp_decl =
new vhdl_signal_decl(name + "_Readable", ref->get_type());
// Add a comment to explain what this is for
tmp_decl->set_comment("Needed to connect outputs");
arch_scope->add_decl(tmp_decl);
parent->get_arch()->add_stmt
(new vhdl_cassign_stmt(from_decl->make_ref(), tmp_decl->make_ref()));
ref = tmp_decl->make_ref();
}
inst->map_port(name.c_str(), ref);
} }
/* /*

View File

@ -248,7 +248,7 @@ vhdl_comp_inst::~vhdl_comp_inst()
} }
void vhdl_comp_inst::map_port(const char *name, vhdl_expr *expr) void vhdl_comp_inst::map_port(const string& name, vhdl_expr *expr)
{ {
port_map_t pmap = { name, expr }; port_map_t pmap = { name, expr };
mapping_.push_back(pmap); mapping_.push_back(pmap);

View File

@ -695,7 +695,7 @@ public:
~vhdl_comp_inst(); ~vhdl_comp_inst();
void emit(std::ostream &of, int level) const; void emit(std::ostream &of, int level) const;
void map_port(const char *name, vhdl_expr *expr); void map_port(const string& name, vhdl_expr *expr);
const std::string &get_comp_name() const { return comp_name_; } const std::string &get_comp_name() const { return comp_name_; }
const std::string &get_inst_name() const { return inst_name_; } const std::string &get_inst_name() const { return inst_name_; }