diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 005a36fd0..7d5b8e7ff 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -270,14 +270,33 @@ static void declare_signals(vhdl_entity *ent, ivl_scope_t scope) ivl_signal_t sig = ivl_scope_sig(scope, i); remember_signal(sig, ent->get_arch()->get_scope()); - if (ivl_signal_dimensions(sig) > 0) - error("Arrays not implemented yet"); - - vhdl_type *sig_type = - vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0); - string name(make_safe_name(sig)); rename_signal(sig, name); + + vhdl_type *sig_type; + unsigned dimensions = ivl_signal_dimensions(sig); + if (dimensions > 0) { + // Arrays are implemented by generating a separate type + // declaration for each array, and then declaring a + // signal of that type + + if (dimensions > 1) { + error("> 1 dimension arrays not implemented yet"); + return; + } + + string type_name = name + "_Type"; + vhdl_type *base_type = + vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0); + vhdl_type *array_type = vhdl_type::array_of(base_type, type_name, 1, 0); + vhdl_decl *array_decl = new vhdl_type_decl(type_name.c_str(), array_type); + ent->get_arch()->get_scope()->add_decl(array_decl); + + sig_type = new vhdl_type(*array_type); + } + else + sig_type = + vhdl_type::type_for(ivl_signal_width(sig), ivl_signal_signed(sig) != 0); ivl_signal_port_t mode = ivl_signal_port(sig); switch (mode) { diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 1c4c1a82b..74c106c2b 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -380,11 +380,10 @@ void vhdl_signal_decl::emit(std::ostream &of, int level) const emit_comment(of, level, true); } -void vhdl_type_decl::emit(std::ofstream &of, int level) const +void vhdl_type_decl::emit(std::ostream &of, int level) const { of << "type " << name_ << " is "; - type_->emit(of, level); - of << ";"; + of << type_->get_type_decl_string() << ";"; emit_comment(of, level, true); } diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index d0d7f5ff3..91c1161e6 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -466,7 +466,7 @@ class vhdl_type_decl : public vhdl_decl { public: vhdl_type_decl(const char *name, vhdl_type *base) : vhdl_decl(name, base) {} - void emit(std::ofstream &of, int level) const; + void emit(std::ostream &of, int level) const; }; diff --git a/tgt-vhdl/vhdl_type.cc b/tgt-vhdl/vhdl_type.cc index 38183b36e..e14c3fbe9 100644 --- a/tgt-vhdl/vhdl_type.cc +++ b/tgt-vhdl/vhdl_type.cc @@ -22,6 +22,7 @@ #include #include +#include vhdl_type *vhdl_type::std_logic() @@ -117,16 +118,27 @@ std::string vhdl_type::get_decl_string() const ss << " downto " << lsb_ << ")"; return ss.str(); } + default: + return get_string(); + } +} + +/* + * Like get_decl_string but completely expands array declarations. + */ +std::string vhdl_type::get_type_decl_string() const +{ + switch (name_) { case VHDL_TYPE_ARRAY: { std::ostringstream ss; ss << "array (" << msb_ << " downto " << lsb_ << ") of " << base_->get_decl_string(); - return ss.str(); + return ss.str(); } default: - return get_string(); + return get_decl_string(); } } @@ -135,6 +147,22 @@ void vhdl_type::emit(std::ostream &of, int level) const of << get_decl_string(); } +vhdl_type::vhdl_type(const vhdl_type &other) + : name_(other.name_), msb_(other.msb_), lsb_(other.lsb_), + array_name_(other.array_name_) +{ + if (other.base_ != NULL) + base_ = new vhdl_type(*other.base_); + else + base_ = NULL; +} + +vhdl_type::~vhdl_type() +{ + if (base_ != NULL) + delete base_; +} + vhdl_type *vhdl_type::std_logic_vector(int msb, int lsb) { return new vhdl_type(VHDL_TYPE_STD_LOGIC_VECTOR, msb, lsb); diff --git a/tgt-vhdl/vhdl_type.hh b/tgt-vhdl/vhdl_type.hh index af9e1515b..f3bfb2211 100644 --- a/tgt-vhdl/vhdl_type.hh +++ b/tgt-vhdl/vhdl_type.hh @@ -53,13 +53,17 @@ public: int msb, int lsb) : name_(VHDL_TYPE_ARRAY), msb_(msb), lsb_(lsb), base_(base), array_name_(array_name) {} - - virtual ~vhdl_type() {} + + // Copy constructor + vhdl_type(const vhdl_type &other); + + virtual ~vhdl_type(); void emit(std::ostream &of, int level) const; vhdl_type_name_t get_name() const { return name_; } std::string get_string() const; std::string get_decl_string() const; + std::string get_type_decl_string() const; vhdl_type *get_base() const; int get_width() const { return msb_ - lsb_ + 1; } int get_msb() const { return msb_; }