From 3bd480a375ee1e1c04f6b20ebeabd90b9be8a1b2 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 13 Jul 2008 12:41:02 +0100 Subject: [PATCH] Allow ouput to be read if connected to child output If output P of A is connected to output Q of B (and A is instantiated inside B) then VHDL does not allow B to read the value of Q (also P), but Verilog does. To get around this the output Q is mapped to P_Sig which is then connected to P, this allows B to read the value of P/Q via P_Sig. --- tgt-vhdl/scope.cc | 44 ++++++++++++++++++++++++++++++++++++++++- tgt-vhdl/vhdl.cc | 10 ++++++++++ tgt-vhdl/vhdl_syntax.cc | 1 + tgt-vhdl/vhdl_syntax.hh | 1 + tgt-vhdl/vhdl_target.h | 1 + 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index a798efbd9..b01207bf8 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -389,7 +389,49 @@ static void map_signal(ivl_signal_t to, vhdl_entity *parent, std::string name = make_safe_name(to); vhdl_var_ref *to_ref; if ((to_ref = dynamic_cast(to_e))) { - inst->map_port(name.c_str(), to_ref); + // 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. + // To get around this we create an internal signal name_Sig + // that takes the value of the output and can be read. + vhdl_decl *decl = + parent->get_arch()->get_scope()->get_decl(to_ref->get_name()); + vhdl_port_decl *pdecl; + if ((pdecl = dynamic_cast(decl)) + && pdecl->get_mode() == VHDL_PORT_OUT) { + + // We need to create a readable signal to shadow this output + std::string shadow_name(to_ref->get_name()); + shadow_name += "_Sig"; + + vhdl_signal_decl *shadow = + new vhdl_signal_decl(shadow_name.c_str(), + new vhdl_type(*decl->get_type())); + shadow->set_comment("Needed to make output readable"); + + parent->get_arch()->get_scope()->add_decl(shadow); + + // Make a continuous assignment of the shadow to the output + parent->get_arch()->add_stmt + (new vhdl_cassign_stmt + (to_ref, new vhdl_var_ref(shadow_name.c_str(), NULL))); + + // Make sure any future references to this signal read the + // shadow not the output + ivl_signal_t sig = find_signal_named(to_ref->get_name(), + parent->get_arch()->get_scope()); + rename_signal(sig, shadow_name); + + // Finally map the child port to the shadow signal + inst->map_port(name.c_str(), + new vhdl_var_ref(shadow_name.c_str(), NULL)); + } + else { + // Not an output port declaration therefore we can + // definitely read it + inst->map_port(name.c_str(), to_ref); + } } else { // Not a static expression diff --git a/tgt-vhdl/vhdl.cc b/tgt-vhdl/vhdl.cc index c8563c488..382f51b49 100644 --- a/tgt-vhdl/vhdl.cc +++ b/tgt-vhdl/vhdl.cc @@ -130,6 +130,16 @@ const std::string &get_renamed_signal(ivl_signal_t sig) return g_known_signals[sig].renamed; } +ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope) +{ + signal_defn_map_t::const_iterator it; + for (it = g_known_signals.begin(); it != g_known_signals.end(); ++it) { + if ((*it).second.scope == scope && (*it).second.renamed == name) + return (*it).first; + } + assert(false); +} + ivl_design_t get_vhdl_design() { return g_design; diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index d509ebc00..fdae262b9 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -88,6 +88,7 @@ void vhdl_entity::emit(std::ostream &of, int level) const of << "use ieee.std_logic_1164.all;" << std::endl; of << "use ieee.numeric_std.all;" << std::endl; of << "use std.textio.all;" << std::endl; + //of << "use work.verilog_support.all;" << std::endl; of << std::endl; emit_comment(of, level); diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 89b26d217..c866ee370 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -501,6 +501,7 @@ public: : vhdl_decl(name, type), mode_(mode) {} void emit(std::ostream &of, int level) const; + vhdl_port_mode_t get_mode() const { return mode_; } private: vhdl_port_mode_t mode_; }; diff --git a/tgt-vhdl/vhdl_target.h b/tgt-vhdl/vhdl_target.h index c70870ca2..10438ce19 100644 --- a/tgt-vhdl/vhdl_target.h +++ b/tgt-vhdl/vhdl_target.h @@ -33,6 +33,7 @@ void remember_signal(ivl_signal_t sig, const vhdl_scope *scope); void rename_signal(ivl_signal_t sig, const std::string &renamed); const vhdl_scope *find_scope_for_signal(ivl_signal_t sig); const std::string &get_renamed_signal(ivl_signal_t sig); +ivl_signal_t find_signal_named(const std::string &name, const vhdl_scope *scope); void blocking_assign_to(vhdl_procedural *proc, ivl_signal_t sig); std::string strip_var(const std::string &str);