diff --git a/tgt-vhdl/scope.cc b/tgt-vhdl/scope.cc index 641228bb3..be5a92720 100644 --- a/tgt-vhdl/scope.cc +++ b/tgt-vhdl/scope.cc @@ -70,11 +70,34 @@ static int draw_module(ivl_scope_t scope, ivl_scope_t parent) { assert(ivl_scope_type(scope) == IVL_SCT_MODULE); + // Maybe we need to create this entity first? vhdl_entity *ent = find_entity(ivl_scope_tname(scope)); if (NULL == ent) ent = create_entity_for(scope); assert(ent); + + // Is this module instantiated inside another? + if (parent != NULL) { + vhdl_entity *parent_ent = find_entity(ivl_scope_tname(parent)); + assert(parent_ent != NULL); + vhdl_arch *parent_arch = parent_ent->get_arch(); + assert(parent_arch != NULL); + // Create a forward declaration for it + if (!parent_arch->have_declared_component(ent->get_name())) { + vhdl_decl *comp_decl = vhdl_component_decl::component_decl_for(ent); + parent_arch->add_decl(comp_decl); + } + + // And an instantiation statement + const char *inst_name = ivl_scope_basename(scope); + vhdl_comp_inst *inst = new vhdl_comp_inst(inst_name, ent->get_name().c_str()); + std::ostringstream ss; + ss << "Scope name " << ivl_scope_name(scope); + inst->set_comment(ss.str()); + parent_arch->add_stmt(inst); + } + return 0; } diff --git a/tgt-vhdl/vhdl_element.cc b/tgt-vhdl/vhdl_element.cc index 4d36a5f16..6578cb1c0 100644 --- a/tgt-vhdl/vhdl_element.cc +++ b/tgt-vhdl/vhdl_element.cc @@ -21,6 +21,9 @@ #include "vhdl_element.hh" #include +#include +#include +#include //////// HELPER FUNCTIONS //////// @@ -120,31 +123,58 @@ vhdl_arch::vhdl_arch(const char *entity, const char *name) vhdl_arch::~vhdl_arch() { - conc_stmt_list_t::iterator it; - for (it = stmts_.begin(); it != stmts_.end(); ++it) + for (conc_stmt_list_t::iterator it = stmts_.begin(); + it != stmts_.end(); + ++it) delete (*it); stmts_.clear(); + + for (decl_list_t::iterator it = decls_.begin(); + it != decls_.end(); + ++it) + delete (*it); + decls_.clear(); } -void vhdl_arch::add_stmt(vhdl_conc_stmt* stmt) +void vhdl_arch::add_stmt(vhdl_conc_stmt *stmt) { stmts_.push_back(stmt); } +void vhdl_arch::add_decl(vhdl_decl *decl) +{ + decls_.push_back(decl); +} + void vhdl_arch::emit(std::ofstream &of, int level) const { emit_comment(of, level); of << "architecture " << name_ << " of " << entity_; of << " is"; - // ...declarations... - // newline(indent(level)); - newline(of, level); + emit_children(of, decls_, level); of << "begin"; emit_children(of, stmts_, level); of << "end architecture;"; blank_line(of, level); // Extra blank line after architectures; } +/* + * True if component `name' has already been declared in this + * architecture. This is a bit of hack, since it uses typeid + * to distinguish between components and other declarations. + */ +bool vhdl_arch::have_declared_component(const std::string &name) const +{ + std::string comp_typename(typeid(vhdl_component_decl).name()); + decl_list_t::const_iterator it; + for (it = decls_.begin(); it != decls_.end(); ++it) { + if (comp_typename == typeid(**it).name() + && (*it)->get_name() == name) + return true; + } + return false; +} + //////// PROCESS //////// @@ -183,3 +213,51 @@ void vhdl_process::emit(std::ofstream &of, int level) const of << "end process;"; newline(of, level); } + + +//////// COMPONENT INSTANTIATION //////// + +vhdl_comp_inst::vhdl_comp_inst(const char *inst_name, const char *comp_name) + : comp_name_(comp_name), inst_name_(inst_name) +{ + +} + +void vhdl_comp_inst::emit(std::ofstream &of, int level) const +{ + // If there are no ports or generics we don't need to mention them... + emit_comment(of, level); + of << inst_name_ << ": " << comp_name_ << ";"; + newline(of, level); +} + + +//////// COMPONENT DECLARATIONS //////// + +vhdl_component_decl::vhdl_component_decl(const char *name) + : vhdl_decl(name) +{ + +} + +/* + * Create a component declaration for the given entity. + */ +vhdl_component_decl *vhdl_component_decl::component_decl_for(const vhdl_entity *ent) +{ + assert(ent != NULL); + + vhdl_component_decl *decl = new vhdl_component_decl + (ent->get_name().c_str()); + + return decl; +} + +void vhdl_component_decl::emit(std::ofstream &of, int level) const +{ + emit_comment(of, level); + of << "component " << name_ << " is"; + // ...ports... + newline(of, level); + of << "end component;"; +} diff --git a/tgt-vhdl/vhdl_element.hh b/tgt-vhdl/vhdl_element.hh index e60127025..b178ff325 100644 --- a/tgt-vhdl/vhdl_element.hh +++ b/tgt-vhdl/vhdl_element.hh @@ -25,6 +25,8 @@ #include #include +class vhdl_entity; + /* * Any VHDL syntax element. Each element can also contain a comment. */ @@ -66,6 +68,60 @@ public: typedef std::list seq_stmt_list_t; +/* + * A declaration of some sort (variable, component, etc.). + * Declarations have names, which is the identifier of the variable, + * constant, etc. not the type. + */ +class vhdl_decl : public vhdl_element { +public: + vhdl_decl(const char *name) : name_(name) {} + virtual ~vhdl_decl() {}; + + const std::string &get_name() const { return name_; } +protected: + std::string name_; +}; + +typedef std::list decl_list_t; + + +/* + * A forward declaration of a component. At the moment it is assumed + * that components declarations will only ever be for entities + * generated by this code generator. This is enforced by making the + * constructor private (use component_decl_for instead). + */ +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; +private: + vhdl_component_decl(const char *name); + + // TODO: Ports, etc. +}; + + +/* + * Instantiation of component. This is really only a placeholder + * at the moment until the port mappings are worked out. + */ +class vhdl_comp_inst : public vhdl_conc_stmt { +public: + vhdl_comp_inst(const char *inst_name, const char *comp_name); + virtual ~vhdl_comp_inst() {} + + void emit(std::ofstream &of, int level) const; +private: + std::string comp_name_, inst_name_; + + // TODO: Port mappings, etc. +}; + /* * Container for sequential statements. @@ -76,7 +132,7 @@ public: virtual ~vhdl_process(); void emit(std::ofstream &of, int level) const; - void add_stmt(vhdl_seq_stmt* stmt); + void add_stmt(vhdl_seq_stmt *stmt); private: seq_stmt_list_t stmts_; std::string name_; @@ -84,8 +140,7 @@ private: /* - * An architecture which implements an entity. Entities are `derived' - * from instantiations of Verilog module scopes in the hierarchy. + * An architecture which implements an entity. */ class vhdl_arch : public vhdl_element { public: @@ -93,16 +148,20 @@ public: virtual ~vhdl_arch(); void emit(std::ofstream &of, int level=0) const; - void add_stmt(vhdl_conc_stmt* stmt); + bool have_declared_component(const std::string &name) const; + void add_decl(vhdl_decl *decl); + void add_stmt(vhdl_conc_stmt *stmt); private: conc_stmt_list_t stmts_; + decl_list_t decls_; std::string name_, entity_; }; /* * An entity defines the ports, parameters, etc. of a module. Each * entity is associated with a single architecture (although - * technically this need not be the case). + * technically this need not be the case). Entities are `derived' + * from instantiations of Verilog module scopes in the hierarchy. */ class vhdl_entity : public vhdl_element { public: