diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index b25d8b5f1..4f7f78397 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -74,7 +74,7 @@ static vhdl_expr *inputs_to_expr(vhdl_arch *arch, vhdl_binop_t op, } /* - * Covert a gate intput to an unary expression. + * Convert a gate intput to an unary expression. */ static vhdl_expr *input_to_expr(vhdl_arch *arch, vhdl_unaryop_t op, ivl_net_logic_t log) @@ -137,9 +137,26 @@ static void declare_signals(vhdl_arch *arch, ivl_scope_t scope) sig_type = vhdl_type::std_logic(); else sig_type = vhdl_type::std_logic_vector(width-1, 0); - vhdl_signal_decl *decl = - new vhdl_signal_decl(ivl_signal_basename(sig), sig_type); - arch->add_decl(decl); + + const char *name = ivl_signal_basename(sig); + ivl_signal_port_t mode = ivl_signal_port(sig); + switch (mode) { + case IVL_SIP_NONE: + arch->add_decl(new vhdl_signal_decl(name, sig_type)); + break; + case IVL_SIP_INPUT: + arch->get_parent()->add_port + (new vhdl_port_decl(name, sig_type, VHDL_PORT_IN)); + break; + case IVL_SIP_OUTPUT: + arch->get_parent()->add_port + (new vhdl_port_decl(name, sig_type, VHDL_PORT_OUT)); + break; + case IVL_SIP_INOUT: + arch->get_parent()->add_port + (new vhdl_port_decl(name, sig_type, VHDL_PORT_INOUT)); + break; + } } } diff --git a/tgt-vhdl/vhdl_syntax.cc b/tgt-vhdl/vhdl_syntax.cc index 1c029aef2..f25449108 100644 --- a/tgt-vhdl/vhdl_syntax.cc +++ b/tgt-vhdl/vhdl_syntax.cc @@ -22,6 +22,7 @@ #include "vhdl_helper.hh" #include +#include vhdl_entity::vhdl_entity(const char *name, const char *derived_from, vhdl_arch *arch) @@ -33,6 +34,7 @@ vhdl_entity::vhdl_entity(const char *name, const char *derived_from, vhdl_entity::~vhdl_entity() { delete arch_; + delete_children(ports_); } /* @@ -50,6 +52,24 @@ void vhdl_entity::requires_package(const char *spec) uses_.push_back(spec); } +/* + * Find a port declaration by name + */ +vhdl_decl *vhdl_entity::get_decl(const std::string &name) const +{ + decl_list_t::const_iterator it; + for (it = ports_.begin(); it != ports_.end(); ++it) { + if ((*it)->get_name() == name) + return *it; + } + return NULL; +} + +void vhdl_entity::add_port(vhdl_port_decl *decl) +{ + ports_.push_back(decl); +} + void vhdl_entity::emit(std::ofstream &of, int level) const { // Pretty much every design will use std_logic so we @@ -121,7 +141,10 @@ vhdl_decl *vhdl_arch::get_decl(const std::string &name) const if ((*it)->get_name() == name) return *it; } - return NULL; + + // Maybe it's a port rather than an internal signal? + assert(parent_); + return parent_->get_decl(name); } /* @@ -286,10 +309,31 @@ void vhdl_wait_stmt::emit(std::ofstream &of, int level) const of << ";"; } - -vhdl_var_decl::~vhdl_var_decl() +vhdl_decl::~vhdl_decl() { - delete type_; + if (type_ != NULL) + delete type_; +} + +void vhdl_port_decl::emit(std::ofstream &of, int level) const +{ + of << name_ << " : "; + + switch (mode_) { + case VHDL_PORT_IN: + of << "in "; + break; + case VHDL_PORT_OUT: + of << "out "; + break; + case VHDL_PORT_INOUT: + of << "inout "; + break; + } + + type_->emit(of, level); + of << ";"; + emit_comment(of, level, true); } void vhdl_var_decl::emit(std::ofstream &of, int level) const @@ -300,11 +344,6 @@ void vhdl_var_decl::emit(std::ofstream &of, int level) const emit_comment(of, level, true); } -vhdl_signal_decl::~vhdl_signal_decl() -{ - delete type_; -} - void vhdl_signal_decl::emit(std::ofstream &of, int level) const { of << "signal " << name_ << " : "; diff --git a/tgt-vhdl/vhdl_syntax.hh b/tgt-vhdl/vhdl_syntax.hh index 12f14cfff..0b85a2ff1 100644 --- a/tgt-vhdl/vhdl_syntax.hh +++ b/tgt-vhdl/vhdl_syntax.hh @@ -276,7 +276,7 @@ class vhdl_decl : public vhdl_element { public: vhdl_decl(const char *name, vhdl_type *type=NULL) : name_(name), type_(type) {} - virtual ~vhdl_decl() {}; + virtual ~vhdl_decl(); const std::string &get_name() const { return name_; } const vhdl_type *get_type() const { return type_; } @@ -296,8 +296,6 @@ typedef std::list decl_list_t; */ class vhdl_component_decl : public vhdl_decl { public: - virtual ~vhdl_component_decl() {}; - static vhdl_component_decl *component_decl_for(const vhdl_entity *ent); void emit(std::ofstream &of, int level) const; @@ -316,8 +314,6 @@ class vhdl_var_decl : public vhdl_decl { public: vhdl_var_decl(const char *name, vhdl_type *type) : vhdl_decl(name, type) {} - ~vhdl_var_decl(); - void emit(std::ofstream &of, int level) const; }; @@ -329,9 +325,30 @@ class vhdl_signal_decl : public vhdl_decl { public: vhdl_signal_decl(const char *name, vhdl_type *type) : vhdl_decl(name, type) {} - ~vhdl_signal_decl(); + virtual void emit(std::ofstream &of, int level) const; +}; + + +enum vhdl_port_mode_t { + VHDL_PORT_IN, + VHDL_PORT_OUT, + VHDL_PORT_INOUT, +}; + +/* + * A port declaration is like a signal declaration except + * it has a direction and appears in the entity rather than + * the architecture. + */ +class vhdl_port_decl : public vhdl_decl { +public: + vhdl_port_decl(const char *name, vhdl_type *type, + vhdl_port_mode_t mode) + : vhdl_decl(name, type), mode_(mode) {} void emit(std::ofstream &of, int level) const; +private: + vhdl_port_mode_t mode_; }; @@ -409,7 +426,9 @@ public: virtual ~vhdl_entity(); void emit(std::ofstream &of, int level=0) const; + void add_port(vhdl_port_decl *decl); vhdl_arch *get_arch() const { return arch_; } + vhdl_decl *get_decl(const std::string &name) const; const std::string &get_name() const { return name_; } void requires_package(const char *spec); const std::string &get_derived_from() const { return derived_from_; } @@ -418,6 +437,7 @@ private: vhdl_arch *arch_; // Entity may only have a single architecture std::string derived_from_; string_list_t uses_; + decl_list_t ports_; }; typedef std::list entity_list_t;